diff -Nru a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/cli-sti-removal.txt Wed Jul 24 14:03:39 2002 @@ -0,0 +1,134 @@ + +#### cli()/sti() removal guide, started by Ingo Molnar + + +as of 2.5.28, five popular macros have been removed on SMP, and +are being phased out on UP: + + cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags) + +until now it was possible to protect driver code against interrupt +handlers via a cli(), but from now on other, more lightweight methods +have to be used for synchronization, such as spinlocks or semaphores. + +for example, driver code that used to do something like: + + struct driver_data; + + irq_handler (...) + { + .... + driver_data.finish = 1; + driver_data.new_work = 0; + .... + } + + ... + + ioctl_func (...) + { + ... + cli(); + ... + driver_data.finish = 0; + driver_data.new_work = 2; + ... + sti(); + ... + } + +was SMP-correct because the cli() function ensured that no +interrupt handler (amongst them the above irq_handler()) function +would execute while the cli()-ed section is executing. + +but from now on a more direct method of locking has to be used: + + spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; + struct driver_data; + + irq_handler (...) + { + unsigned long flags; + .... + spin_lock_irqsave(&driver_lock, flags); + .... + driver_data.finish = 1; + driver_data.new_work = 0; + .... + spin_unlock_irqrestore(&driver_lock, flags); + .... + } + + ... + + ioctl_func (...) + { + ... + spin_lock_irq(&driver_lock); + ... + driver_data.finish = 0; + driver_data.new_work = 2; + ... + spin_unlock_irq(&driver_lock); + ... + } + +the above code has a number of advantages: + +- the locking relation is easier to understand - actual lock usage + pinpoints the critical sections. cli() usage is too opaque. + Easier to understand means it's easier to debug. + +- it's faster, because spinlocks are faster to acquire than the + potentially heavily-used IRQ lock. Furthermore, your driver does + not have to wait eg. for a big heavy SCSI interrupt to finish, + because the driver_lock spinlock is only used by your driver. + cli() on the other hand was used by many drivers, and extended + the critical section to the whole IRQ handler function - creating + serious lock contention. + + +to make the transition easier, we've still kept the cli(), sti(), +save_flags(), save_flags_cli() and restore_flags() macros defined +on UP systems - but their usage will be phased out until 2.6 is +released. + +drivers that want to disable local interrupts (interrupts on the +current CPU), can use the following five macros: + + local_irq_disable(), local_irq_enable(), local_irq_save(flags), + local_irq_save_off(flags), local_irq_restore(flags) + +but beware, their meaning and semantics are much simpler, far from +that of the old cli(), sti(), save_flags(flags) and restore_flags(flags) +SMP meaning: + + local_irq_disable() => turn local IRQs off + + local_irq_enable() => turn local IRQs on + + local_irq_save(flags) => save the current IRQ state into flags. The + state can be on or off. (on some + architectures there's even more bits in it.) + + local_irq_save_off(flags) => save the current IRQ state into flags and + disable interrupts. + + local_irq_restore(flags) => restore the IRQ state from flags. + +(local_irq_save can save both irqs on and irqs off state, and +local_irq_restore can restore into both irqs on and irqs off state.) + +another related change is that synchronize_irq() now takes a parameter: +synchronize_irq(irq). This change too has the purpose of making SMP +to make the transition easier, we've still kept the cli(), sti(), +save_flags() and restore_flags() macros defined on UP systems - but +their usage will be phased out until the 2.6 kernel is released. + + +why were these changes done? The main reason was the architectural burden +of maintaining the cli()/sti() interface - it became a real problem. The +new interrupt system is much more streamlined, easier to understand, debug, +and it's also a bit faster - the same happened to it that will happen to +cli()/sti() using drivers once they convert to spinlocks :-) + diff -Nru a/Documentation/fb/README-sstfb.txt b/Documentation/fb/README-sstfb.txt --- a/Documentation/fb/README-sstfb.txt Wed Jul 24 14:03:36 2002 +++ b/Documentation/fb/README-sstfb.txt Wed Jul 24 14:03:36 2002 @@ -9,12 +9,12 @@ combinations and it seems that it works. The main page is located at , and if you want the latest version, check out the CVS, as the driver is a work - in progress, i feel incomfortable with releasing tarballs of something + in progress, I feel uncomfortable with releasing tarballs of something not completely working...Don't worry, it's still more than useable (I eat my own dog food) Please read the Bug section, and report any success or failure to me - (Ghozlane Toumi ). + (Ghozlane Toumi ). BTW, If you have only one monitor , and you don't feel like playing with the vga passthrou cable, I can only suggest borrowing a screen somewhere... @@ -22,8 +22,9 @@ Installation - This driver (should) work on ix86, with any 2.2.x kernel (tested + This driver (should) work on ix86, with "late" 2.2.x kernel (tested with x = 19) and "recent" 2.4.x kernel, as a module or compiled in. + It has been included in mainstream kernel since the infamous 2.4.10. You can apply the patches found in sstfb/kernel/*-2.{2|4}.x.patch, and copy sstfb.c to linux/drivers/video/, or apply a single patch, sstfb/patch-2.{2|4}.x-sstfb-yymmdd to your linux source tree. @@ -41,7 +42,7 @@ module, the 3dfx takes control of the output, so you'll have to plug the monitor to the "normal" video board in order to issue the commands, or you can blindly use sst_dbg_vgapass - in the tools directory (See Tools). The latest option is pass the + in the tools directory (See Tools). The latest solution is pass the parameter vgapass=1 when insmodding the driver. (See Kernel/Modules Options) @@ -77,36 +78,39 @@ in kernel : video=sstfb:option1,option2:value2,option3 ... sstfb supports the folowing options : - module kernel description - vgapass=1 vgapass enable or disable VGA passthrou cable - vgapass=0 vganopass when enabled, the monitor will - get the signal from the VGA board - and not from the voodoo. default nopass - - mem=x mem:x force frame buffer memory in MiB - allowed values: 1, 2, 4. default detect - - inverse=1 inverse suposed to enable inverse console. - doesn't work ... - - clipping=1 clipping enable or disable clipping . with - clipping=0 noclipping clipping enabled, all offscreen reads - and writes are disgarded. default: - enable clipping. - - gfxclk=x gfxclk:x force graphic clock frequency (in MHz) - becarefull with this option . - default is 50Mhz for voodoo1, 75MHz - for voodoo2. Be carefull, this one is - dangerous. default=auto - - slowpci=0 slowpci enable or disable fast PCI read/writes - slowpci=1 fastpci default : fastpci - - dev=x dev:x attach the driver to device number x - 0 is the first compatible board (in - lspci order) +Module Kernel Description + +vgapass=0 vganopass Enable or disable VGA passthrou cable. +vgapass=1 vgapass When enabled, the monitor will get the signal + from the VGA board and not from the voodoo. + Default: nopass + +mem=x mem:x Force frame buffer memory in MiB + allowed values: 0, 1, 2, 4. + Default: 0 (= autodetect) + +inverse=1 inverse Supposed to enable inverse console. + doesn't work yet... + +clipping=1 clipping Enable or disable clipping. +clipping=0 noclipping With clipping enabled, all offscreen + reads and writes are disgarded. + Default: enable clipping. + +gfxclk=x gfxclk:x Force graphic clock frequency (in MHz). + Be carefull with this option, it may be + DANGEROUS. + Default: auto + 50Mhz for Voodoo 1, + 75MHz for Voodoo 2. + +slowpci=1 fastpci Enable or disable fast PCI read/writes. +slowpci=1 slowpci Default : fastpci + +dev=x dev:x Attach the driver to device number x. + 0 is the first compatible board (in + lspci order) Tools @@ -126,8 +130,8 @@ - DO NOT use glide while the sstfb module is in, you'll most likely hang your computer. - - if you see some artefacts (pixels not cleaning and stuff like that), - try turning off clipping (clipping=0) + - If you see some artefacts (pixels not cleaning and stuff like that), + try turning off clipping (clipping=0), and/or using slowpci - the driver don't detect the 4Mb frame buffer voodoos, it seems that the 2 last Mbs wrap around. looking into that . - The driver is 16 bpp only, 24/32 won't work. @@ -137,8 +141,8 @@ patterns at the border of your windows (the pixels loose the lowest byte -> basicaly the blue component nd some of the green) . I'm unable to reproduce this with XFree86-3.3, but one of the testers has this - problem with XFree86-4. I don't know yet if this is the drivers fault - or X's (most likely the driver, of course). + problem with XFree86-4. apparently recent Xfree86-4.x solve this + problem. - I didn't really test changing the palette, so you may find some weird things when playing with that. - Sometimes the driver will not recognise the DAC , and the @@ -147,6 +151,9 @@ contact me . - the 24/32 is not likely to work anytime soon , knowing that the hardware does ... unusual thigs in 24/32 bpp + - When used with anther video board, current limitations of linux + console subsystem can cause some troubles, specificaly, you should + disable software scrollback , as it can oops badly ... Todo @@ -154,14 +161,14 @@ - Buy more coffee. - test/port to other arch. - try to add panning using tweeks with front and back buffer . - - try to implement accel en voodoo2 , this board can actualy do a + - try to implement accel on voodoo2 , this board can actualy do a lot in 2D even if it was sold as a 3D only board ... ghoz. -- -Ghozlane Toumi +Ghozlane Toumi -$Date: 2001/08/29 00:21:11 $ +$Date: 2002/05/09 20:11:45 $ http://sstfb.sourceforge.net/README diff -Nru a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog --- a/Documentation/filesystems/devfs/ChangeLog Wed Jul 24 14:03:36 2002 +++ b/Documentation/filesystems/devfs/ChangeLog Wed Jul 24 14:03:36 2002 @@ -1931,3 +1931,13 @@ - Protected and from changing directory contents +=============================================================================== +Changes for patch v214 + +- Switched to ISO C structure field initialisers + +- Switch to set_current_state() and move before add_wait_queue() + +- Updated README from master HTML file + +- Fixed devfs entry leak in when *readdir fails diff -Nru a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README --- a/Documentation/filesystems/devfs/README Wed Jul 24 14:03:37 2002 +++ b/Documentation/filesystems/devfs/README Wed Jul 24 14:03:37 2002 @@ -3,7 +3,7 @@ Linux Devfs (Device File System) FAQ Richard Gooch -7-APR-2002 +21-JUL-2002 Document languages: @@ -788,6 +788,9 @@ make sure the kernel does not mount devfs at boot time +make sure you have a correct /dev/console entry in your +root file-system (where your disc-based /dev lives) + create the /dev-state directory @@ -1288,9 +1291,10 @@ SCSI Generic Devices -All SCSI CD-ROMs are placed under /dev/sg. A similar naming -scheme is used as for SCSI discs. A SCSI generic device with the -parameters:c=1,b=2,t=3,u=4 would appear as: +The generic (aka. raw) interface for all SCSI devices are placed under +/dev/sg. A similar naming scheme is used as for SCSI discs. A +SCSI generic device with the parameters:c=1,b=2,t=3,u=4 would appear +as: /dev/sg/c1b2t3u4 @@ -1603,6 +1607,23 @@ then mount(8) will fail to find devices. The solution is to make sure that devfs is mounted on /dev. See above for how to do that. + + +I have extra or incorrect entries in /dev + +You may have stale entries in your dev-state area. Check for a +RESTORE configuration line in your devfsd configuration +(typically /etc/devfsd.conf). If you have this line, check +the contents of the specified directory for stale entries. Remove +any entries which are incorrect, then reboot. + + +I get "Unable to open initial console" messages at boot + +This usually happens when you don't have devfs automounted onto +/dev at boot time, and there is no valid +/dev/console entry on your root file-system. Create a valid +/dev/console device node. diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt --- a/Documentation/filesystems/jfs.txt Wed Jul 24 14:03:38 2002 +++ b/Documentation/filesystems/jfs.txt Wed Jul 24 14:03:38 2002 @@ -1,136 +1,38 @@ -IBM's Journaled File System (JFS) for Linux version 1.0.15 +IBM's Journaled File System (JFS) for Linux + +JFS Homepage: http://oss.software.ibm.com/jfs/ + Team members +------------ Steve Best sbest@us.ibm.com Dave Kleikamp shaggy@austin.ibm.com Barry Arndt barndt@us.ibm.com -Christoph Hellwig hch@caldera.de - - -Release February 15, 2002 (version 1.0.15) - -This is our fifty-third release of IBM's Enterprise JFS technology port to Linux. -Beta 1 was release 0.1.0 on 12/8/2000, Beta 2 was release 0.2.0 on 3/7/2001, -Beta 3 was release 0.3.0 on 4/30/2001, and release 1.0.0 on 6/28/2001. - -The changelog.jfs file contains detailed information of changes done in each source -code drop. - -JFS has a source tree that can be built on 2.4.3 - 2.4.17 and 2.5.4 kernel.org -source trees. - -Our current goal on the 2.5.x series of the kernel is to update to the latest -2.5.x version and only support the latest version of this kernel. -This will change when the distros start shipping the 2.5.x series of the kernel. - -Our current goal on the 2.4.x series of the kernel is to continue to support -all of the kernels in this series as we do today. - -There is an anonymous cvs access available for the JFS tree. The steps below are -what is needed to pull the JFS cvs tree from the oss.software.ibm.com server. - -id anoncvs -password anoncvs - -To checkout 2.4.x series of the JFS files do the following: -CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs -cvs checkout linux24 - -To checkout 2.5.2 series of the JFS files do the following: -CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs -cvs checkout linux25 - -To checkout the JFS utilities do the following: -CVSROOT should be set to :pserver:anoncvs@oss.software.ibm.com:/usr/cvs/jfs -cvs checkout jfsutils - -The cvs tree contains the latest changes being done to JFS. To receive notification -of commits to the cvs tree, please send e-mail to linuxjfs@us.ibm.com stating that -you would like notifications sent to you. - -The jfs-2.4-1.0.15-patch.tar.gz is the easiest way to get the latest file system -source code on your system. There are also patch files that can move your jfs source -code from one release to another. If you have release 1.0.14 and would like to move -to release 1.0.15 the patch file named jfs-2.4-1_0_14-to-1_0_15-patch.gz will do that. - -The jfs-2.4-1.0.15-patch.tar.gz file contains a readme and patch files for different -levels of the 2.4 kernel. Please see the README in the jfs-2.4-1.0.15-patch.tar.gz -file for help on applying the two patch files. - - -The following files in the kernel source tree have been changed so JFS can be built. -The jfs-2.4-1.0.15.tar.gz source tar ball contains each of the files below with -the extension of the kernel level it is associated with. As an example, there are now -four Config.in files named Config.in-2.4.0, Config.in-2.4.5, Config.in-2.4.7 and -Config.in-2.4.17. - - -If you use the jfs-2.4-1.0.15.tar.gz to build JFS you must rename each of the -kernel files to the file names listed below. The standard kernel from www.kernel.org -is the source of the kernel files that are included in the jfs tar file. - - -In sub dir fs Config.in, Makefile -In sub dir fs/nls Config.in -In sub dir Documentation Configure.help, Changes -In sub dir Documentation/filesystems 00-INDEX -In sub dir linux MAINTAINERS +Christoph Hellwig hch@infradead.org -Please backup the above files before the JFS tar file is added to the kernel source -tree. All JFS files are located in the include/linux/jfs or fs/jfs sub dirs. +The following mount options are supported: -Our development team has used the Linux kernel levels 2.4.3 - 2.4.17 kernels -with gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) -for our port so far. A goal of the JFS team is to have JFS run on all architectures -that Linux supports, there is no architecture specific code in JFS. JFS has been run -on the following architectures (x86, PowerPC, Alpha, s/390, ARM) so far. - -To make JFS build, during the "make config" step of building the kernel answer y to -the Prompt for development and/or incomplete code/drivers in the Code maturity level -options section. In the Filesystems section use the m for the answer to -JFS filesystem support (experimental) (CONFIG_JFS_FS) [Y/m/n?] - - -Build in /usr/src/linux with the command: - - -make modules -make modules_install - -If you rebuild jfs.o after having mounted and unmounted a partition, "modprobe -r jfs" -will unload the old module. - -For the file system debugging messages are being written to /var/log/messages. - -Please see the readme in the utilities package for information about building -the JFS utilities. +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. JFS TODO list: Plans for our near term development items - - get defrag capabilities operational in the FS - - get extendfs capabilities operational in the FS - - test EXTENDFS utility, for growing JFS partitions - - test defrag utility, calls file system to defrag the file system. - - add support for block sizes (512,1024,2048) - - add support for logfile on dedicated partition + - implement online resize for extending JFS volumes + - enhance support for logfile on dedicated partition + - get access control list functionality operational + - get extended attributes functionality operational - Longer term work items - - get access control list functionality operational - - get extended attributes functionality operational + - 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 linuxjfs@us.ibm.com. -The JFS mailing list can be subscribed to by using the link labeled "Mail list Subscribe" -at our web page http://oss.software.ibm.com/jfs/. - - - - - - - - +The JFS mailing list can be subscribed to by using the link labeled +"Mail list Subscribe" at our web page http://oss.software.ibm.com/jfs/. diff -Nru a/Documentation/preempt-locking.txt b/Documentation/preempt-locking.txt --- a/Documentation/preempt-locking.txt Wed Jul 24 14:03:35 2002 +++ b/Documentation/preempt-locking.txt Wed Jul 24 14:03:35 2002 @@ -70,7 +70,8 @@ preempt_enable() decrement the preempt counter preempt_disable() increment the preempt counter preempt_enable_no_resched() decrement, but do not immediately preempt -preempt_get_count() return the preempt counter +preempt_check_resched() if needed, reschedule +preempt_count() return the preempt counter The functions are nestable. In other words, you can call preempt_disable n-times in a code path, and preemption will not be reenabled until the n-th @@ -80,6 +81,13 @@ Note that you do not need to explicitly prevent preemption if you are holding any locks or interrupts are disabled, since preemption is implicitly disabled in those cases. + +But keep in mind that 'irqs disabled' is a fundamentally unsafe way of +disabling preemption - any spin_unlock() decreasing the preemption count +to 0 might trigger a reschedule. A simple printk() might trigger a reschedule. +So use this implicit preemption-disabling property only if you know that the +affected codepath does not do any of this. Best policy is to use this only for +small, atomic code that you wrote and which calls no complex functions. Example: diff -Nru a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt --- a/Documentation/s390/cds.txt Wed Jul 24 14:03:36 2002 +++ b/Documentation/s390/cds.txt Wed Jul 24 14:03:36 2002 @@ -885,8 +885,8 @@ Prior to call do_IO() the device driver must assure disabled state, i.e. the I/O mask value in the PSW must be disabled. This can be accomplished by calling -__save_flags( flags). The current PSW flags are preserved and can be restored -by __restore_flags( flags) at a later time. +local_save_flags( flags). The current PSW flags are preserved and can be restored +by local_irq_restore( flags) at a later time. If the device driver violates this rule while running in a uni-processor environment an interrupt might be presented prior to the do_IO() routine diff -Nru a/Documentation/serial/driver b/Documentation/serial/driver --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/serial/driver Wed Jul 24 14:03:39 2002 @@ -0,0 +1,300 @@ + + Low Level Serial API + -------------------- + + + $Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $ + + +This document is meant as a brief overview of some aspects of the new serial +driver. It is not complete, any questions you have should be directed to + + +The reference implementation is contained within serial_amba.c. + + + +Low Level Serial Hardware Driver +-------------------------------- + +The low level serial hardware driver is responsible for supplying port +information (defined by uart_port) and a set of control methods (defined +by uart_ops) to the core serial driver. The low level driver is also +responsible for handling interrupts for the port, and providing any +console support. + + +Console Support +--------------- + +The serial core provides a few helper functions. This includes identifing +the correct port structure (via uart_get_console) and decoding command line +arguments (uart_parse_options). + + +Locking +------- + +It is the responsibility of the low level hardware driver to perform the +necessary locking using port->lock. There are some exceptions (which +are described in the uart_ops listing below.) + +There are three locks. A per-port spinlock, a per-port tmpbuf semaphore, +and an overall semaphore. + +From the core driver perspective, the port->lock locks the following +data: + + port->mctrl + port->icount + info->xmit.head (circ->head) + info->xmit.tail (circ->tail) + +The low level driver is free to use this lock to provide any additional +locking. + +The core driver uses the info->tmpbuf_sem lock to prevent multi-threaded +access to the info->tmpbuf bouncebuffer used for port writes. + +The port_sem semaphore is used to protect against ports being added/ +removed or reconfigured at inappropriate times. + + +uart_ops +-------- + +The uart_ops structure is the main interface between serial_core and the +hardware specific driver. It contains all the methods to control the +hardware. + + tx_empty(port) + This function tests whether the transmitter fifo and shifter + for the port described by 'port' is empty. If it is empty, + this function should return TIOCSER_TEMT, otherwise return 0. + If the port does not support this operation, then it should + return TIOCSER_TEMT. + + Locking: none. + Interrupts: caller dependent. + This call must not sleep + + set_mctrl(port, mctrl) + This function sets the modem control lines for port described + by 'port' to the state described by mctrl. The relevant bits + of mctrl are: + - TIOCM_RTS RTS signal. + - TIOCM_DTR DTR signal. + - TIOCM_OUT1 OUT1 signal. + - TIOCM_OUT2 OUT2 signal. + If the appropriate bit is set, the signal should be driven + active. If the bit is clear, the signal should be driven + inactive. + + Locking: port->lock taken. + Interrupts: locally disabled. + This call must not sleep + + get_mctrl(port) + Returns the current state of modem control inputs. The state + of the outputs should not be returned, since the core keeps + track of their state. The state information should include: + - TIOCM_DCD state of DCD signal + - TIOCM_CTS state of CTS signal + - TIOCM_DSR state of DSR signal + - TIOCM_RI state of RI signal + The bit is set if the signal is currently driven active. If + the port does not support CTS, DCD or DSR, the driver should + indicate that the signal is permanently active. If RI is + not available, the signal should not be indicated as active. + + Locking: none. + Interrupts: caller dependent. + This call must not sleep + + stop_tx(port,tty_stop) + Stop transmitting characters. This might be due to the CTS + line becoming inactive or the tty layer indicating we want + to stop transmission. + + tty_stop: 1 if this call is due to the TTY layer issuing a + TTY stop to the driver (equiv to rs_stop). + + Locking: port->lock taken. + Interrupts: caller dependent. + This call must not sleep + + start_tx(port,tty_start) + start transmitting characters. (incidentally, nonempty will + always be nonzero, and shouldn't be used - it will be dropped). + + tty_start: 1 if this call was due to the TTY layer issuing + a TTY start to the driver (equiv to rs_start) + + Locking: port->lock taken. + Interrupts: locally disabled. + This call must not sleep + + stop_rx(port) + Stop receiving characters; the port is in the process of + being closed. + + Locking: none. + Interrupts: caller dependent. + This call must not sleep + + enable_ms(port) + Enable the modem status interrupts. + + Locking: none. + Interrupts: caller dependent. + + break_ctl(port,ctl) + Control the transmission of a break signal. If ctl is + nonzero, the break signal should be transmitted. The signal + should be terminated when another call is made with a zero + ctl. + + Locking: none. + Interrupts: caller dependent. + This call must not sleep + + startup(port) + Grab any interrupt resources and initialise any low level driver + state. Enable the port for reception. It should not activate + RTS nor DTR; this will be done via a separate call to set_mctrl. + + Locking: port_sem taken. + Interrupts: globally disabled. + + shutdown(port) + Disable the port, disable any break condition that may be in + effect, and free any interrupt resources. It should not disable + RTS nor DTR; this will have already been done via a separate + call to set_mctrl. + + Locking: port_sem taken. + Interrupts: caller dependent. + + change_speed(port,cflag,iflag,quot) + Change the port parameters, including word length, parity, stop + bits. Update read_status_mask and ignore_status_mask to indicate + the types of events we are interested in receiving. Relevant + cflag bits are: + CSIZE - word size + CSTOPB - 2 stop bits + PARENB - parity enable + PARODD - odd parity (when PARENB is in force) + CREAD - enable reception of characters (if not set, + still receive characters from the port, but + throw them away. + CRTSCTS - if set, enable CTS status change reporting + CLOCAL - if not set, enable modem status change + reporting. + Relevant iflag bits are: + INPCK - enable frame and parity error events to be + passed to the TTY layer. + BRKINT + PARMRK - both of these enable break events to be + passed to the TTY layer. + + IGNPAR - ignore parity and framing errors + IGNBRK - ignore break errors, If IGNPAR is also + set, ignore overrun errors as well. + The interaction of the iflag bits is as follows (parity error + given as an example): + Parity error INPCK IGNPAR + None n/a n/a character received + Yes n/a 0 character discarded + Yes 0 1 character received, marked as + TTY_NORMAL + Yes 1 1 character received, marked as + TTY_PARITY + + Locking: none. + Interrupts: caller dependent. + This call must not sleep + + pm(port,state,oldstate) + perform any power management related activities on the specified + port. state indicates the new state (defined by ACPI D0-D3), + oldstate indicates the previous state. Essentially, D0 means + fully on, D3 means powered down. + + This function should not be used to grab any resources. + + Locking: none. + Interrupts: caller dependent. + + type(port) + Return a pointer to a string constant describing the specified + port, or return NULL, in which case the string 'unknown' is + substituted. + + Locking: none. + Interrupts: caller dependent. + + release_port(port) + Release any memory and IO region resources currently in use by + the port. + + Locking: none. + Interrupts: caller dependent. + + request_port(port) + Request any memory and IO region resources required by the port. + If any fail, no resources should be registered when this function + returns, and it should return -EBUSY on failure. + + Locking: none. + Interrupts: caller dependent. + + config_port(port,type) + Perform any autoconfiguration steps required for the port. `type` + contains a bit mask of the required configuration. UART_CONFIG_TYPE + indicates that the port requires detection and identification. + port->type should be set to the type found, or PORT_UNKNOWN if + no port was detected. + + UART_CONFIG_IRQ indicates autoconfiguration of the interrupt signal, + which should be probed using standard kernel autoprobing techniques. + This is not necessary on platforms where ports have interrupts + internally hard wired (eg, system on a chip implementations). + + Locking: none. + Interrupts: caller dependent. + + verify_port(port,serinfo) + Verify the new serial port information contained within serinfo is + suitable for this port type. + + Locking: none. + Interrupts: caller dependent. + + ioctl(port,cmd,arg) + Perform any port specific IOCTLs. IOCTL commands must be defined + using the standard numbering system found in + + Locking: none. + Interrupts: caller dependent. + + +Other notes +----------- + +It is intended some day to drop the 'unused' entries from uart_port, and +allow low level drivers to register their own individual uart_port's with +the core. This will allow drivers to use uart_port as a pointer to a +structure containing both the uart_port entry with their own extensions, +thus: + + struct my_port { + struct uart_port port; + int my_stuff; + }; + +Todo +---- + +Please see the BUGS file in CVS at + + http://cvs.arm.linux.org.uk/cgi/viewcvs.cgi/serial/BUGS diff -Nru a/Makefile b/Makefile --- a/Makefile Wed Jul 24 14:03:36 2002 +++ b/Makefile Wed Jul 24 14:03:36 2002 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 27 +SUBLEVEL = 28 EXTRAVERSION = # *DOCUMENTATION* @@ -212,7 +212,7 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH) -CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \ +CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -g \ -fomit-frame-pointer -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) diff -Nru a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c --- a/arch/alpha/kernel/core_apecs.c Wed Jul 24 14:03:37 2002 +++ b/arch/alpha/kernel/core_apecs.c Wed Jul 24 14:03:37 2002 @@ -131,7 +131,7 @@ unsigned int stat0, value; unsigned int haxr2 = 0; - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); @@ -201,7 +201,7 @@ *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; mb(); } - __restore_flags(flags); + local_irq_restore(flags); return value; } @@ -213,7 +213,7 @@ unsigned int stat0; unsigned int haxr2 = 0; - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ /* Reset status register to avoid losing errors. */ stat0 = *(vuip)APECS_IOC_DCSR; @@ -269,7 +269,7 @@ *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; mb(); } - __restore_flags(flags); + local_irq_restore(flags); } static int diff -Nru a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c --- a/arch/alpha/kernel/core_cia.c Wed Jul 24 14:03:38 2002 +++ b/arch/alpha/kernel/core_cia.c Wed Jul 24 14:03:38 2002 @@ -113,7 +113,7 @@ int cia_cfg = 0; DBGC(("conf_read(addr=0x%lx, type1=%d) ", addr, type1)); - __save_and_cli(flags); + local_irq_save(flags); /* Reset status register to avoid losing errors. */ stat0 = *(vip)CIA_IOC_CIA_ERR; @@ -154,7 +154,7 @@ *(vip)CIA_IOC_CFG; } - __restore_flags(flags); + local_irq_restore(flags); DBGC(("done\n")); return value; @@ -167,7 +167,7 @@ int stat0, cia_cfg = 0; DBGC(("conf_write(addr=0x%lx, type1=%d) ", addr, type1)); - __save_and_cli(flags); + local_irq_save(flags); /* Reset status register to avoid losing errors. */ stat0 = *(vip)CIA_IOC_CIA_ERR; @@ -204,7 +204,7 @@ *(vip)CIA_IOC_CFG; } - __restore_flags(flags); + local_irq_restore(flags); DBGC(("done\n")); } diff -Nru a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c --- a/arch/alpha/kernel/core_lca.c Wed Jul 24 14:03:37 2002 +++ b/arch/alpha/kernel/core_lca.c Wed Jul 24 14:03:37 2002 @@ -132,7 +132,7 @@ unsigned long flags, code, stat0; unsigned int value; - __save_and_cli(flags); + local_irq_save(flags); /* Reset status register to avoid loosing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; @@ -160,7 +160,7 @@ value = 0xffffffff; } - __restore_flags(flags); + local_irq_restore(flags); return value; } @@ -169,7 +169,7 @@ { unsigned long flags, code, stat0; - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ /* Reset status register to avoid loosing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; @@ -195,7 +195,7 @@ /* Reset machine check. */ wrmces(0x7); } - __restore_flags(flags); + local_irq_restore(flags); } static int diff -Nru a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c --- a/arch/alpha/kernel/core_mcpcia.c Wed Jul 24 14:03:35 2002 +++ b/arch/alpha/kernel/core_mcpcia.c Wed Jul 24 14:03:35 2002 @@ -97,7 +97,7 @@ cpu = smp_processor_id(); - __save_and_cli(flags); + local_irq_save(flags); DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n", addr, type1, mid)); @@ -131,7 +131,7 @@ DBG_CFG(("conf_read(): finished\n")); - __restore_flags(flags); + local_irq_restore(flags); return value; } @@ -145,7 +145,7 @@ cpu = smp_processor_id(); - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ /* Reset status register to avoid losing errors. */ stat0 = *(vuip)MCPCIA_CAP_ERR(mid); @@ -167,7 +167,7 @@ mb(); DBG_CFG(("conf_write(): finished\n")); - __restore_flags(flags); + local_irq_restore(flags); } static int diff -Nru a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c --- a/arch/alpha/kernel/core_t2.c Wed Jul 24 14:03:35 2002 +++ b/arch/alpha/kernel/core_t2.c Wed Jul 24 14:03:35 2002 @@ -132,7 +132,7 @@ cpu = smp_processor_id(); - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); @@ -181,7 +181,7 @@ } DBG(("conf_read(): finished\n")); - __restore_flags(flags); + local_irq_restore(flags); return value; } @@ -194,7 +194,7 @@ cpu = smp_processor_id(); - __save_and_cli(flags); /* avoid getting hit by machine check */ + local_irq_save(flags); /* avoid getting hit by machine check */ #if 0 { @@ -234,7 +234,7 @@ mb(); } DBG(("conf_write(): finished\n")); - __restore_flags(flags); + local_irq_restore(flags); } static int diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Wed Jul 24 14:03:39 2002 +++ b/arch/alpha/kernel/irq.c Wed Jul 24 14:03:39 2002 @@ -85,9 +85,9 @@ do { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); else - __cli(); + local_irq_disable(); status |= action->flags; action->handler(irq, action->dev_id, regs); @@ -95,7 +95,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); irq_exit(cpu, irq); diff -Nru a/arch/alpha/kernel/irq_smp.c b/arch/alpha/kernel/irq_smp.c --- a/arch/alpha/kernel/irq_smp.c Wed Jul 24 14:03:35 2002 +++ b/arch/alpha/kernel/irq_smp.c Wed Jul 24 14:03:35 2002 @@ -85,9 +85,9 @@ show("wait_on_irq", where); count = MAXCOUNT; } - __sti(); + local_irq_enable(); udelay(1); /* make sure to run pending irqs */ - __cli(); + local_irq_disable(); if (irqs_running()) continue; @@ -153,7 +153,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -171,7 +171,7 @@ unsigned long flags; int cpu = smp_processor_id(); - __save_flags(flags); + local_save_flags(flags); local_enabled = (!(flags & 7)); /* default to local */ retval = 2 + local_enabled; @@ -197,10 +197,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk(KERN_ERR "global_restore_flags: %08lx (%p)\n", diff -Nru a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c --- a/arch/alpha/kernel/ns87312.c Wed Jul 24 14:03:37 2002 +++ b/arch/alpha/kernel/ns87312.c Wed Jul 24 14:03:37 2002 @@ -28,11 +28,11 @@ int data; unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); outb(0, ide_base); /* set the index register for reg #0 */ data = inb(ide_base+1); /* read the current contents */ outb(0, ide_base); /* set the index register for reg #0 */ outb(data | 0x40, ide_base+1); /* turn on IDE */ outb(data | 0x40, ide_base+1); /* turn on IDE, really! */ - __restore_flags(flags); + local_irq_restore(flags); } diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c --- a/arch/alpha/kernel/process.c Wed Jul 24 14:03:37 2002 +++ b/arch/alpha/kernel/process.c Wed Jul 24 14:03:37 2002 @@ -88,7 +88,7 @@ int cpuid = smp_processor_id(); /* No point in taking interrupts anymore. */ - __cli(); + local_irq_disable(); cpup = (struct percpu_struct *) ((unsigned long)hwrpb + hwrpb->processor_offset diff -Nru a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c --- a/arch/alpha/kernel/smc37c669.c Wed Jul 24 14:03:38 2002 +++ b/arch/alpha/kernel/smc37c669.c Wed Jul 24 14:03:38 2002 @@ -2486,7 +2486,7 @@ SMC37c669_CONFIG_REGS *SMC_base; unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) { #if SMC_DEBUG SMC37c669_config_mode( TRUE ); @@ -2541,12 +2541,12 @@ SMC37c669_config_mode( FALSE ); SMC37c669_display_device_info( ); #endif - __restore_flags(flags); + local_irq_restore(flags); printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n", (unsigned long) SMC_base ); } else { - __restore_flags(flags); + local_irq_restore(flags); #if SMC_DEBUG printk( "No SMC37c669 Super I/O Controller found\n" ); #endif diff -Nru a/arch/alpha/kernel/smc37c93x.c b/arch/alpha/kernel/smc37c93x.c --- a/arch/alpha/kernel/smc37c93x.c Wed Jul 24 14:03:38 2002 +++ b/arch/alpha/kernel/smc37c93x.c Wed Jul 24 14:03:38 2002 @@ -243,7 +243,7 @@ unsigned long SMCUltraBase; unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) { #if SMC_DEBUG SMCReportDeviceStatus(SMCUltraBase); @@ -264,13 +264,13 @@ SMCReportDeviceStatus(SMCUltraBase); #endif SMCRunState(SMCUltraBase); - __restore_flags(flags); + local_irq_restore(flags); printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n", SMCUltraBase); return 1; } else { - __restore_flags(flags); + local_irq_restore(flags); DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n")); return 0; } diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c --- a/arch/alpha/kernel/smp.c Wed Jul 24 14:03:37 2002 +++ b/arch/alpha/kernel/smp.c Wed Jul 24 14:03:37 2002 @@ -175,7 +175,7 @@ current->active_mm = &init_mm; /* Must have completely accurate bogos. */ - __sti(); + local_irq_enable(); /* Wait boot CPU to stop with irq enabled before running calibrate_delay. */ diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Wed Jul 24 14:03:35 2002 +++ b/arch/arm/kernel/irq.c Wed Jul 24 14:03:35 2002 @@ -190,7 +190,7 @@ spin_unlock(&irq_controller_lock); if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); status = 0; do { diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c --- a/arch/cris/kernel/irq.c Wed Jul 24 14:03:39 2002 +++ b/arch/cris/kernel/irq.c Wed Jul 24 14:03:39 2002 @@ -266,7 +266,7 @@ action = irq_action[irq]; if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = irq_action[irq]; do_random = 0; do { @@ -276,7 +276,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } irq_exit(cpu); diff -Nru a/arch/i386/boot/video.S b/arch/i386/boot/video.S --- a/arch/i386/boot/video.S Wed Jul 24 14:03:36 2002 +++ b/arch/i386/boot/video.S Wed Jul 24 14:03:36 2002 @@ -96,7 +96,7 @@ #define PARAM_VESAPM_SEG 0x2e #define PARAM_VESAPM_OFF 0x30 #define PARAM_LFB_PAGES 0x32 - +#define PARAM_VESA_ATTRIB 0x34 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN @@ -221,6 +221,8 @@ movl %eax, %fs:(PARAM_LFB_COLORS) movl 35(%di), %eax movl %eax, %fs:(PARAM_LFB_COLORS+4) + movw 0(%di), %ax + movw %ax, %fs:(PARAM_VESA_ATTRIB) # get video mem size leaw modelist+1024, %di diff -Nru a/arch/i386/config.in b/arch/i386/config.in --- a/arch/i386/config.in Wed Jul 24 14:03:37 2002 +++ b/arch/i386/config.in Wed Jul 24 14:03:37 2002 @@ -185,10 +185,6 @@ 4GB CONFIG_HIGHMEM4G \ 64GB CONFIG_HIGHMEM64G" off -if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then - bool 'Use high memory pte support' CONFIG_HIGHPTE -fi - if [ "$CONFIG_HIGHMEM4G" = "y" ]; then define_bool CONFIG_HIGHMEM y fi diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c Wed Jul 24 14:03:39 2002 +++ b/arch/i386/kernel/apic.c Wed Jul 24 14:03:39 2002 @@ -485,13 +485,12 @@ apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); - __save_flags(flags); - __cli(); + local_irq_save(flags); disable_local_APIC(); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_ENABLE; wrmsr(MSR_IA32_APICBASE, l, h); - __restore_flags(flags); + local_irq_restore(flags); } static void apic_pm_resume(void *data) @@ -499,8 +498,7 @@ unsigned int l, h; unsigned long flags; - __save_flags(flags); - __cli(); + local_irq_save(flags); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; @@ -523,7 +521,7 @@ apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); - __restore_flags(flags); + local_irq_restore(flags); if (apic_pm_state.perfctr_pmdev) pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data); } @@ -804,8 +802,8 @@ unsigned long flags; int delta; - __save_flags(flags); - __sti(); + local_save_flags(flags); + local_irq_enable(); /* * ok, Intel has some smart code in their APIC that knows * if a CPU was in 'hlt' lowpower mode, and this increases @@ -842,7 +840,7 @@ printk("CPU%d\n", smp_processor_id(), t0, t1, delta, slice, clocks); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -935,7 +933,7 @@ printk("Using local APIC timer interrupts.\n"); using_apic_timer = 1; - __cli(); + local_irq_disable(); calibration_result = calibrate_APIC_clock(); /* @@ -943,7 +941,7 @@ */ setup_APIC_timer((void *)calibration_result); - __sti(); + local_irq_enable(); /* and update all other cpus */ smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1); @@ -1084,12 +1082,9 @@ * Besides, if we don't timer interrupts ignore the global * interrupt lock, which is the WrongThing (tm) to do. */ - irq_enter(cpu, 0); + irq_enter(); smp_local_timer_interrupt(®s); - irq_exit(cpu, 0); - - if (softirq_pending(cpu)) - do_softirq(); + irq_exit(); } /* @@ -1099,6 +1094,7 @@ { unsigned long v; + irq_enter(); /* * Check if this really is a spurious interrupt and ACK it * if it is a vectored one. Just in case... @@ -1111,6 +1107,7 @@ /* see sw-dev-man vol 3, chapter 7.4.13.5 */ printk(KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n", smp_processor_id()); + irq_exit(); } /* @@ -1121,6 +1118,7 @@ { unsigned long v, v1; + irq_enter(); /* First tickle the hardware, only then report what went on. -- REW */ v = apic_read(APIC_ESR); apic_write(APIC_ESR, 0); @@ -1140,6 +1138,7 @@ */ printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n", smp_processor_id(), v , v1); + irq_exit(); } /* diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/kernel/apm.c Wed Jul 24 14:03:35 2002 @@ -222,6 +222,8 @@ #include +extern rwlock_t xtime_lock; +extern spinlock_t i8253_lock; extern unsigned long get_cmos_time(void); extern void machine_real_restart(unsigned char *, int); @@ -512,9 +514,9 @@ */ #define APM_DO_CLI \ if (apm_info.allow_ints) \ - __sti(); \ + local_irq_enable(); \ else \ - __cli(); + local_irq_disable(); #ifdef APM_ZERO_SEGS # define APM_DECL_SEGS \ @@ -568,7 +570,7 @@ APM_DECL_SEGS unsigned long flags; - __save_flags(flags); + local_save_flags(flags); APM_DO_CLI; APM_DO_SAVE_SEGS; /* @@ -588,7 +590,7 @@ : "a" (func), "b" (ebx_in), "c" (ecx_in) : "memory", "cc"); APM_DO_RESTORE_SEGS; - __restore_flags(flags); + local_irq_restore(flags); return *eax & 0xff; } @@ -612,7 +614,7 @@ APM_DECL_SEGS unsigned long flags; - __save_flags(flags); + local_save_flags(flags); APM_DO_CLI; APM_DO_SAVE_SEGS; { @@ -636,7 +638,7 @@ : "memory", "cc"); } APM_DO_RESTORE_SEGS; - __restore_flags(flags); + local_irq_restore(flags); return error; } @@ -1141,40 +1143,25 @@ static void set_time(void) { - unsigned long flags; - - if (got_clock_diff) { /* Must know time zone in order to set clock */ - save_flags(flags); - cli(); + if (got_clock_diff) /* Must know time zone in order to set clock */ CURRENT_TIME = get_cmos_time() + clock_cmos_diff; - restore_flags(flags); - } } static void get_time_diff(void) { #ifndef CONFIG_APM_RTC_IS_GMT - unsigned long flags; - /* * Estimate time zone so that set_time can update the clock */ - save_flags(flags); clock_cmos_diff = -get_cmos_time(); - cli(); clock_cmos_diff += CURRENT_TIME; got_clock_diff = 1; - restore_flags(flags); #endif } -static void reinit_timer(void) +static inline void reinit_timer(void) { #ifdef INIT_TIMER_AFTER_SUSPEND - unsigned long flags; - - save_flags(flags); - cli(); /* set the clock to 100 Hz */ outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ udelay(10); @@ -1182,7 +1169,6 @@ udelay(10); outb(LATCH >> 8 , 0x40); /* MSB */ udelay(10); - restore_flags(flags); #endif } @@ -1203,13 +1189,21 @@ } printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n"); } + /* serialize with the timer interrupt */ + write_lock_irq(&xtime_lock); + + /* protect against access to timer chip registers */ + spin_lock(&i8253_lock); + get_time_diff(); - cli(); err = set_system_power_state(APM_STATE_SUSPEND); reinit_timer(); set_time(); ignore_normal_resume = 1; - sti(); + + spin_unlock(&i8253_lock); + write_unlock_irq(&xtime_lock); + if (err == APM_NO_ERROR) err = APM_SUCCESS; if (err != APM_SUCCESS) @@ -1232,8 +1226,12 @@ { int err; + /* serialize with the timer interrupt */ + write_lock_irq(&xtime_lock); /* If needed, notify drivers here */ get_time_diff(); + write_unlock_irq(&xtime_lock); + err = set_system_power_state(APM_STATE_STANDBY); if ((err != APM_SUCCESS) && (err != APM_NO_ERROR)) apm_error("standby", err); @@ -1321,7 +1319,9 @@ ignore_bounce = 1; if ((event != APM_NORMAL_RESUME) || (ignore_normal_resume == 0)) { + write_lock_irq(&xtime_lock); set_time(); + write_unlock_irq(&xtime_lock); pm_send_all(PM_RESUME, (void *)0); queue_event(event, NULL); } @@ -1336,7 +1336,9 @@ break; case APM_UPDATE_TIME: + write_lock_irq(&xtime_lock); set_time(); + write_unlock_irq(&xtime_lock); break; case APM_CRITICAL_SUSPEND: diff -Nru a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c --- a/arch/i386/kernel/bluesmoke.c Wed Jul 24 14:03:37 2002 +++ b/arch/i386/kernel/bluesmoke.c Wed Jul 24 14:03:37 2002 @@ -10,12 +10,15 @@ #include #include #include +#include + #include #include #include #include #include #include +#include #ifdef CONFIG_X86_MCE @@ -74,7 +77,9 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs regs) { + irq_enter(); vendor_thermal_interrupt(®s); + irq_exit(); } /* P4/Xeon Thermal regulation detect and init */ diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c --- a/arch/i386/kernel/cpu/common.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/kernel/cpu/common.c Wed Jul 24 14:03:35 2002 @@ -426,7 +426,7 @@ if (test_and_set_bit(nr, &cpu_initialized)) { printk(KERN_WARNING "CPU#%d already initialized!\n", nr); - for (;;) __sti(); + for (;;) local_irq_enable(); } printk(KERN_INFO "Initializing CPU#%d\n", nr); diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Wed Jul 24 14:03:37 2002 +++ b/arch/i386/kernel/entry.S Wed Jul 24 14:03:37 2002 @@ -72,12 +72,8 @@ #ifdef CONFIG_PREEMPT #define preempt_stop cli -#define INC_PRE_COUNT(reg) incl TI_PRE_COUNT(reg); -#define DEC_PRE_COUNT(reg) decl TI_PRE_COUNT(reg); #else #define preempt_stop -#define INC_PRE_COUNT(reg) -#define DEC_PRE_COUNT(reg) #define resume_kernel restore_all #endif @@ -189,10 +185,10 @@ # userspace resumption stub bypassing syscall exit tracing ALIGN -ret_from_intr: - preempt_stop - DEC_PRE_COUNT(%ebx) ret_from_exception: + preempt_stop +ret_from_intr: + GET_THREAD_INFO(%ebx) movl EFLAGS(%esp), %eax # mix EFLAGS and CS movb CS(%esp), %al testl $(VM_MASK | 3), %eax @@ -268,7 +264,7 @@ work_notifysig: # deal with pending signals and # notify-resume requests - testl $(VM_MASK),EFLAGS(%esp) + testl $VM_MASK, EFLAGS(%esp) movl %esp, %eax jne work_notifysig_v86 # returning to kernel-space or # vm86-space @@ -338,8 +334,6 @@ ALIGN common_interrupt: SAVE_ALL - GET_THREAD_INFO(%ebx) - INC_PRE_COUNT(%ebx) call do_IRQ jmp ret_from_intr @@ -347,8 +341,6 @@ ENTRY(name) \ pushl $nr-256; \ SAVE_ALL \ - GET_THREAD_INFO(%ebx); \ - INC_PRE_COUNT(%ebx) \ call smp_/**/name; \ jmp ret_from_intr; @@ -408,10 +400,8 @@ movl $(__KERNEL_DS), %edx movl %edx, %ds movl %edx, %es - GET_THREAD_INFO(%ebx) call *%edi addl $8, %esp - preempt_stop jmp ret_from_exception ENTRY(coprocessor_error) @@ -438,7 +428,6 @@ pushl $0 # temporary storage for ORIG_EIP call math_emulate addl $4, %esp - preempt_stop jmp ret_from_exception ENTRY(debug) diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Wed Jul 24 14:03:38 2002 +++ b/arch/i386/kernel/i386_ksyms.c Wed Jul 24 14:03:38 2002 @@ -132,13 +132,7 @@ EXPORT_SYMBOL_NOVERS(__write_lock_failed); EXPORT_SYMBOL_NOVERS(__read_lock_failed); -/* Global SMP irq stuff */ -EXPORT_SYMBOL(synchronize_irq); -EXPORT_SYMBOL(global_irq_holder); -EXPORT_SYMBOL(__global_cli); -EXPORT_SYMBOL(__global_sti); -EXPORT_SYMBOL(__global_save_flags); -EXPORT_SYMBOL(__global_restore_flags); +/* Global SMP stuff */ EXPORT_SYMBOL(smp_call_function); /* TLB flushing */ diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Wed Jul 24 14:03:37 2002 +++ b/arch/i386/kernel/io_apic.c Wed Jul 24 14:03:37 2002 @@ -1219,7 +1219,7 @@ { unsigned int t1 = jiffies; - sti(); + local_irq_enable(); /* Let ten ticks pass... */ mdelay((10 * 1000) / HZ); diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/kernel/irq.c Wed Jul 24 14:03:35 2002 @@ -184,250 +184,16 @@ return 0; } -/* - * Global interrupt locks for SMP. Allow interrupts to come in on any - * CPU, yet make cli/sti act globally to protect critical regions.. - */ - -#ifdef CONFIG_SMP -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */ - -extern void show_stack(unsigned long* esp); - -static void show(char * str) -{ - int i; - int cpu = smp_processor_id(); - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [",irqs_running()); - for(i=0;i < NR_CPUS;i++) - printk(" %d",local_irq_count(i)); - printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0); - for(i=0;i < NR_CPUS;i++) - printk(" %d",local_bh_count(i)); - - printk(" ]\nStack dumps:"); - for(i = 0; i < NR_CPUS; i++) { - unsigned long esp; - if (i == cpu) - continue; - printk("\nCPU %d:",i); - esp = init_tss[i].esp0; - if (!esp) { - /* tss->esp0 is set to NULL in cpu_init(), - * it's initialized when the cpu returns to user - * space. -- manfreds - */ - printk(" "); - continue; - } - esp &= ~(THREAD_SIZE-1); - esp += sizeof(struct thread_info); - show_stack((void*)esp); - } - printk("\nCPU %d:",cpu); - show_stack(NULL); - printk("\n"); -} - -#define MAXCOUNT 100000000 - -/* - * I had a lockup scenario where a tight loop doing - * spin_unlock()/spin_lock() on CPU#1 was racing with - * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but - * apparently the spin_unlock() information did not make it - * through to CPU#0 ... nasty, is this by design, do we have to limit - * 'memory update oscillation frequency' artificially like here? - * - * Such 'high frequency update' races can be avoided by careful design, but - * some of our major constructs like spinlocks use similar techniques, - * it would be nice to clarify this issue. Set this define to 0 if you - * want to check whether your system freezes. I suspect the delay done - * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but - * i thought that such things are guaranteed by design, since we use - * the 'LOCK' prefix. - */ -#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0 - -#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND -# define SYNC_OTHER_CORES(x) udelay(x+1) -#else -/* - * We have to allow irqs to arrive between __sti and __cli - */ -# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") -#endif - -static inline void wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!irqs_running()) - if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) - break; - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - clear_bit(0,&global_irq_lock); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - __sti(); - SYNC_OTHER_CORES(cpu); - __cli(); - if (irqs_running()) - continue; - if (global_irq_lock) - continue; - if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) - continue; - if (!test_and_set_bit(0,&global_irq_lock)) - break; - } - } -} - -/* - * This is called when we want to synchronize with - * interrupts. We may for example tell a device to - * stop sending interrupts: but to make sure there - * are no interrupts that are executing on another - * CPU we need to call this function. - */ -void synchronize_irq(void) -{ - if (irqs_running()) { - /* Stupid approach */ - cli(); - sti(); - } -} - -static inline void get_irqlock(int cpu) -{ - if (test_and_set_bit(0,&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - do { - do { - rep_nop(); - } while (test_bit(0,&global_irq_lock)); - } while (test_and_set_bit(0,&global_irq_lock)); - } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - - /* - * Ok, finally.. - */ - global_irq_holder = cpu; -} - -#define EFLAGS_IF_SHIFT 9 - -/* - * 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 int flags; - - __save_flags(flags); - if (flags & (1 << EFLAGS_IF_SHIFT)) { - int cpu; - __cli(); - cpu = smp_processor_id(); - if (!local_irq_count(cpu)) - get_irqlock(cpu); - } -} - -void __global_sti(void) +#if CONFIG_SMP +inline void synchronize_irq(unsigned int irq) { - int cpu = get_cpu(); - - if (!local_irq_count(cpu)) - release_irqlock(cpu); - __sti(); - put_cpu(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - int cpu = smp_processor_id(); - - __save_flags(flags); - local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1; - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count(cpu)) { - if (local_enabled) - retval = 1; - if (global_irq_holder == cpu) - retval = 0; - } - return retval; -} + /* is there anything to synchronize with? */ + if (!irq_desc[irq].action) + return; -void __global_restore_flags(unsigned long flags) -{ - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - __cli(); - break; - case 3: - __sti(); - break; - default: - printk("global_restore_flags: %08lx (%08lx)\n", - flags, (&flags)[-1]); - } + while (irq_desc[irq].status & IRQ_INPROGRESS) + cpu_relax(); } - #endif /* @@ -439,15 +205,10 @@ */ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { - int status; - int cpu = smp_processor_id(); - - irq_enter(cpu, irq); - - status = 1; /* Force the "do bottom halves" bit */ + int status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -456,9 +217,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); - - irq_exit(cpu, irq); + local_irq_disable(); return status; } @@ -511,13 +270,7 @@ void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - cpu_relax(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } + synchronize_irq(irq); } /** @@ -581,6 +334,7 @@ struct irqaction * action; unsigned int status; + irq_enter(); kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); @@ -640,8 +394,8 @@ desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_pending(cpu)) - do_softirq(); + irq_exit(); + return 1; } @@ -768,13 +522,8 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) { - barrier(); - cpu_relax(); - } -#endif + synchronize_irq(irq); kfree(action); return; } @@ -826,7 +575,7 @@ /* Wait for longstanding interrupts to trigger. */ for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ synchronize_irq(); + /* about 20ms delay */ barrier(); /* * enable any unassigned irqs @@ -849,7 +598,7 @@ * Wait for spurious interrupts to trigger */ for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ synchronize_irq(); + /* about 100ms delay */ barrier(); /* * Now filter out any obviously spurious interrupts diff -Nru a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c --- a/arch/i386/kernel/ldt.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/kernel/ldt.c Wed Jul 24 14:03:36 2002 @@ -107,7 +107,8 @@ void release_segments(struct mm_struct *mm) { if (mm->context.size) { - clear_LDT(); + if (mm == current->active_mm) + clear_LDT(); if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else diff -Nru a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c --- a/arch/i386/kernel/mca.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/kernel/mca.c Wed Jul 24 14:03:36 2002 @@ -102,6 +102,12 @@ static struct MCA_info* mca_info = NULL; +/* + * Motherboard register spinlock. Untested on SMP at the moment, but + * are there any MCA SMP boxes? + */ +static spinlock_t mca_lock = SPIN_LOCK_UNLOCKED; + /* MCA registers */ #define MCA_MOTHERBOARD_SETUP_REG 0x94 @@ -213,8 +219,11 @@ } memset(mca_info, 0, sizeof(struct MCA_info)); - save_flags(flags); - cli(); + /* + * We do not expect many MCA interrupts during initialization, + * but let us be safe: + */ + spin_lock_irq(&mca_lock); /* Make sure adapter setup is off */ @@ -300,8 +309,7 @@ outb_p(0, MCA_ADAPTER_SETUP_REG); /* Enable interrupts and return memory start */ - - restore_flags(flags); + spin_unlock_irq(&mca_lock); for (i = 0; i < MCA_STANDARD_RESOURCES; i++) request_resource(&ioport_resource, mca_standard_resources + i); @@ -514,8 +522,7 @@ if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0; if(reg < 0 || reg >= 8) return 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&mca_lock, flags); /* Make sure motherboard setup is off */ @@ -566,7 +573,7 @@ mca_info->slot[slot].pos[reg] = byte; - restore_flags(flags); + spin_unlock_irqrestore(&mca_lock, flags); return byte; } /* mca_read_pos() */ @@ -610,8 +617,7 @@ if(mca_info == NULL) return; - save_flags(flags); - cli(); + spin_lock_irqsave(&mca_lock, flags); /* Make sure motherboard setup is off */ @@ -623,7 +629,7 @@ outb_p(byte, MCA_POS_REG(reg)); outb_p(0, MCA_ADAPTER_SETUP_REG); - restore_flags(flags); + spin_unlock_irqrestore(&mca_lock, flags); /* Update the global register list, while we have the byte */ diff -Nru a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c --- a/arch/i386/kernel/mtrr.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/kernel/mtrr.c Wed Jul 24 14:03:35 2002 @@ -381,7 +381,7 @@ static void set_mtrr_prepare_save (struct set_mtrr_context *ctxt) { /* Disable interrupts locally */ - __save_flags (ctxt->flags); __cli (); + local_irq_save(ctxt->flags); if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) return; @@ -428,7 +428,7 @@ static void set_mtrr_done (struct set_mtrr_context *ctxt) { if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) { - __restore_flags (ctxt->flags); + local_irq_restore (ctxt->flags); return; } @@ -452,7 +452,7 @@ write_cr4(ctxt->cr4val); /* Re-enable interrupts locally (if enabled previously) */ - __restore_flags (ctxt->flags); + local_irq_restore (ctxt->flags); } /* End Function set_mtrr_done */ /* This function returns the number of variable MTRRs */ @@ -546,7 +546,7 @@ arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */ /* Save flags and disable interrupts */ - __save_flags (flags); __cli (); + local_irq_save(flags); ccr3 = getCx86 (CX86_CCR3); setCx86 (CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ @@ -557,7 +557,7 @@ setCx86 (CX86_CCR3, ccr3); /* disable MAPEN */ /* Enable interrupts if it was enabled previously */ - __restore_flags (flags); + local_irq_restore (flags); shift = ((unsigned char *) base)[1] & 0x0f; *base >>= PAGE_SHIFT; diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c --- a/arch/i386/kernel/nmi.c Wed Jul 24 14:03:38 2002 +++ b/arch/i386/kernel/nmi.c Wed Jul 24 14:03:38 2002 @@ -78,7 +78,7 @@ printk(KERN_INFO "testing NMI watchdog ... "); memcpy(tmp, irq_stat, sizeof(tmp)); - sti(); + local_irq_enable(); mdelay((10*1000)/nmi_hz); // wait 10 ticks for (cpu = 0; cpu < NR_CPUS; cpu++) { diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/kernel/process.c Wed Jul 24 14:03:35 2002 @@ -89,11 +89,11 @@ void default_idle(void) { if (current_cpu_data.hlt_works_ok && !hlt_counter) { - __cli(); + local_irq_disable(); if (!need_resched()) safe_halt(); else - __sti(); + local_irq_enable(); } } @@ -106,7 +106,7 @@ { int oldval; - __sti(); + local_irq_enable(); /* * Deal with another CPU just having chosen a thread to @@ -290,7 +290,7 @@ { unsigned long flags; - cli(); + local_irq_disable(); /* Write zero to CMOS register number 0x0f, which the BIOS POST routine will recognize as telling it to do a proper reboot. (Well diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/kernel/smp.c Wed Jul 24 14:03:36 2002 @@ -161,9 +161,7 @@ unsigned long cfg; unsigned long flags; - __save_flags(flags); - __cli(); - + local_irq_save(flags); /* * Wait for idle. @@ -186,7 +184,7 @@ */ apic_write_around(APIC_ICR, cfg); - __restore_flags(flags); + local_irq_restore(flags); } static inline void send_IPI_mask_sequence(int mask, int vector) @@ -200,8 +198,7 @@ * should be modified to do 1 message per cluster ID - mbligh */ - __save_flags(flags); - __cli(); + local_irq_save(flags); for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) { query_mask = 1 << query_cpu; @@ -229,7 +226,7 @@ apic_write_around(APIC_ICR, cfg); } } - __restore_flags(flags); + local_irq_restore(flags); } static inline void send_IPI_mask(int mask, int vector) @@ -387,7 +384,7 @@ clear_bit(cpu, &flush_cpumask); out: - put_cpu(); + put_cpu_no_resched(); } static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, @@ -603,7 +600,7 @@ * Remove this CPU: */ clear_bit(smp_processor_id(), &cpu_online_map); - __cli(); + local_irq_disable(); disable_local_APIC(); if (cpu_data[smp_processor_id()].hlt_works_ok) for(;;) __asm__("hlt"); @@ -618,9 +615,9 @@ { smp_call_function(stop_this_cpu, NULL, 1, 0); - __cli(); + local_irq_disable(); disable_local_APIC(); - __sti(); + local_irq_enable(); } /* diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Wed Jul 24 14:03:38 2002 +++ b/arch/i386/kernel/smpboot.c Wed Jul 24 14:03:38 2002 @@ -453,7 +453,7 @@ clear_local_APIC(); setup_local_APIC(); - __sti(); + local_irq_enable(); #ifdef CONFIG_MTRR /* @@ -1060,7 +1060,6 @@ boot_cpu_logical_apicid = logical_smp_processor_id(); map_cpu_to_boot_apicid(0, boot_cpu_apicid); - global_irq_holder = NO_PROC_ID; current_thread_info()->cpu = 0; smp_tune_scheduling(); diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/kernel/vm86.c Wed Jul 24 14:03:36 2002 @@ -571,6 +571,8 @@ struct task_struct *tsk; int sig; } vm86_irqs[16]; + +static spinlock_t irqbits_lock = SPIN_LOCK_UNLOCKED; static int irqbits; #define ALLOWED_SIGS ( 1 /* 0 = don't send a signal */ \ @@ -580,9 +582,8 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) { int irq_bit; unsigned long flags; - - save_flags(flags); - cli(); + + spin_lock_irqsave(&irqbits_lock, flags); irq_bit = 1 << intno; if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk) goto out; @@ -591,14 +592,19 @@ send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1); /* else user will poll for IRQs */ out: - restore_flags(flags); + spin_unlock_irqrestore(&irqbits_lock, flags); } static inline void free_vm86_irq(int irqnumber) { + unsigned long flags; + free_irq(irqnumber,0); vm86_irqs[irqnumber].tsk = 0; + + spin_lock_irqsave(&irqbits_lock, flags); irqbits &= ~(1 << irqnumber); + spin_unlock_irqrestore(&irqbits_lock, flags); } static inline int task_valid(struct task_struct *tsk) @@ -635,11 +641,10 @@ if ( (irqnumber<3) || (irqnumber>15) ) return 0; if (vm86_irqs[irqnumber].tsk != current) return 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&irqbits_lock, flags); bit = irqbits & (1 << irqnumber); irqbits &= ~bit; - restore_flags(flags); + spin_unlock_irqrestore(&irqbits_lock, flags); return bit; } diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/mm/fault.c Wed Jul 24 14:03:35 2002 @@ -107,27 +107,25 @@ */ void bust_spinlocks(int yes) { + int loglevel_save = console_loglevel; + spin_lock_init(&timerlist_lock); if (yes) { oops_in_progress = 1; -#ifdef CONFIG_SMP - global_irq_lock = 0; /* Many serial drivers do __global_cli() */ -#endif - } else { - int loglevel_save = console_loglevel; + return; + } #ifdef CONFIG_VT - unblank_screen(); + unblank_screen(); #endif - oops_in_progress = 0; - /* - * OK, the message is on the console. Now we call printk() - * without oops_in_progress set so that printk will give klogd - * a poke. Hold onto your hats... - */ - console_loglevel = 15; /* NMI oopser may have shut the console up */ - printk(" "); - console_loglevel = loglevel_save; - } + oops_in_progress = 0; + /* + * OK, the message is on the console. Now we call printk() + * without oops_in_progress set so that printk will give klogd + * a poke. Hold onto your hats... + */ + console_loglevel = 15; /* NMI oopser may have shut the console up */ + printk(" "); + console_loglevel = loglevel_save; } asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c --- a/arch/i386/mm/ioremap.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/mm/ioremap.c Wed Jul 24 14:03:36 2002 @@ -215,7 +215,7 @@ struct vm_struct *p; if (addr <= high_memory) return; - p = remove_kernel_area(PAGE_MASK & (unsigned long) addr); + p = remove_kernel_area((void *) (PAGE_MASK & (unsigned long) addr)); if (!p) { printk("__iounmap: bad address %p\n", addr); return; diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c --- a/arch/i386/pci/direct.c Wed Jul 24 14:03:36 2002 +++ b/arch/i386/pci/direct.c Wed Jul 24 14:03:36 2002 @@ -306,7 +306,7 @@ unsigned int tmp; unsigned long flags; - __save_flags(flags); __cli(); + local_irq_save(flags); /* * Check if configuration type 1 works. @@ -318,7 +318,7 @@ if (inl (0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) { outl (tmp, 0xCF8); - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_INFO "PCI: Using configuration type 1\n"); if (!request_region(0xCF8, 8, "PCI conf1")) return NULL; @@ -336,7 +336,7 @@ outb (0x00, 0xCFA); if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 && pci_sanity_check(&pci_direct_conf2)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_INFO "PCI: Using configuration type 2\n"); if (!request_region(0xCF8, 4, "PCI conf2")) return NULL; @@ -344,7 +344,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return NULL; } diff -Nru a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c --- a/arch/i386/pci/pcbios.c Wed Jul 24 14:03:35 2002 +++ b/arch/i386/pci/pcbios.c Wed Jul 24 14:03:35 2002 @@ -82,7 +82,7 @@ unsigned long entry; /* %edx */ unsigned long flags; - __save_flags(flags); __cli(); + local_irq_save(flags); __asm__("lcall *(%%edi); cld" : "=a" (return_code), "=b" (address), @@ -91,7 +91,7 @@ : "0" (service), "1" (0), "D" (&bios32_indirect)); - __restore_flags(flags); + local_irq_restore(flags); switch (return_code) { case 0: @@ -122,7 +122,7 @@ if ((pcibios_entry = bios32_service(PCI_SERVICE))) { pci_indirect.address = pcibios_entry + PAGE_OFFSET; - __save_flags(flags); __cli(); + local_irq_save(flags); __asm__( "lcall *(%%edi); cld\n\t" "jc 1f\n\t" @@ -135,7 +135,7 @@ : "1" (PCIBIOS_PCI_BIOS_PRESENT), "D" (&pci_indirect) : "memory"); - __restore_flags(flags); + local_irq_restore(flags); status = (eax >> 8) & 0xff; hw_mech = eax & 0xff; diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Wed Jul 24 14:03:38 2002 +++ b/arch/ia64/hp/sim/simscsi.c Wed Jul 24 14:03:38 2002 @@ -144,7 +144,7 @@ } int -simscsi_biosparam (Disk *disk, kdev_t n, int ip[]) +simscsi_biosparam (Disk *disk, struct block_device *n, int ip[]) { int size = disk->capacity; diff -Nru a/arch/ia64/hp/sim/simscsi.h b/arch/ia64/hp/sim/simscsi.h --- a/arch/ia64/hp/sim/simscsi.h Wed Jul 24 14:03:35 2002 +++ b/arch/ia64/hp/sim/simscsi.h Wed Jul 24 14:03:35 2002 @@ -17,7 +17,7 @@ extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); extern int simscsi_abort (Scsi_Cmnd *); extern int simscsi_reset (Scsi_Cmnd *, unsigned int); -extern int simscsi_biosparam (Disk *, kdev_t, int[]); +extern int simscsi_biosparam (Disk *, struct block_device *, int[]); #define SIMSCSI { \ detect: simscsi_detect, \ diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Wed Jul 24 14:03:37 2002 +++ b/arch/ia64/kernel/irq.c Wed Jul 24 14:03:37 2002 @@ -284,7 +284,7 @@ # define SYNC_OTHER_CORES(x) udelay(x+1) #else /* - * We have to allow irqs to arrive between __sti and __cli + * We have to allow irqs to arrive between local_irq_enable and local_irq_disable */ # ifdef CONFIG_IA64 # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0") @@ -317,9 +317,9 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(smp_processor_id()); - __cli(); + local_irq_disable(); if (irqs_running()) continue; if (global_irq_lock) @@ -394,16 +394,16 @@ unsigned int flags; #ifdef CONFIG_IA64 - __save_flags(flags); + local_save_flags(flags); if (flags & IA64_PSR_I) { - __cli(); + local_irq_disable(); if (!really_local_irq_count()) get_irqlock(); } #else - __save_flags(flags); + local_save_flags(flags); if (flags & (1 << EFLAGS_IF_SHIFT)) { - __cli(); + local_irq_disable(); if (!really_local_irq_count()) get_irqlock(); } @@ -414,7 +414,7 @@ { if (!really_local_irq_count()) release_irqlock(smp_processor_id()); - __sti(); + local_irq_enable(); } /* @@ -431,7 +431,7 @@ unsigned long flags; int cpu = smp_processor_id(); - __save_flags(flags); + local_save_flags(flags); #ifdef CONFIG_IA64 local_enabled = (flags & IA64_PSR_I) != 0; #else @@ -460,10 +460,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx (%08lx)\n", @@ -489,7 +489,7 @@ status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -498,7 +498,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); local_irq_exit(irq); diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c --- a/arch/ia64/kernel/smp.c Wed Jul 24 14:03:39 2002 +++ b/arch/ia64/kernel/smp.c Wed Jul 24 14:03:39 2002 @@ -91,7 +91,7 @@ */ clear_bit(smp_processor_id(), &cpu_online_map); max_xtp(); - __cli(); + local_irq_disable(); cpu_halt(); } diff -Nru a/arch/ia64/sn/kernel/llsc4.c b/arch/ia64/sn/kernel/llsc4.c --- a/arch/ia64/sn/kernel/llsc4.c Wed Jul 24 14:03:36 2002 +++ b/arch/ia64/sn/kernel/llsc4.c Wed Jul 24 14:03:36 2002 @@ -1025,7 +1025,7 @@ if (mycpu == NR_CPUS-1) { printk("\nTight loop of cpu %d sending ints to cpu 0 (every 100 us)\n", mycpu); udelay(IS_RUNNING_ON_SIMULATOR ? 1000 : 1000000); - __cli(); + local_irq_disable(); while (1) { smp_send_reschedule(0); udelay(100); diff -Nru a/arch/ia64/sn/kernel/sv.c b/arch/ia64/sn/kernel/sv.c --- a/arch/ia64/sn/kernel/sv.c Wed Jul 24 14:03:36 2002 +++ b/arch/ia64/sn/kernel/sv.c Wed Jul 24 14:03:36 2002 @@ -183,7 +183,7 @@ #ifdef SV_DEBUG_INTERRUPT_STATE { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if(sv->sv_flags & SV_INTS) { if(SV_TEST_INTERRUPTS_ENABLED(flags)) { @@ -279,7 +279,7 @@ #ifdef SV_DEBUG_INTERRUPT_STATE if(sv->sv_flags & SV_INTS) { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if(SV_TEST_INTERRUPTS_ENABLED(flags)) printk(KERN_ERR "sv_signal: SV_INTS and " "interrupts enabled! (flags: 0x%lx)\n", flags); @@ -296,7 +296,7 @@ #ifdef SV_DEBUG_INTERRUPT_STATE if(sv->sv_flags & SV_INTS) { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if(SV_TEST_INTERRUPTS_ENABLED(flags)) printk(KERN_ERR "sv_broadcast: SV_INTS and " "interrupts enabled! (flags: 0x%lx)\n", flags); @@ -475,7 +475,7 @@ printk("ITW: thread %d started.\n", id); while(1) { - __save_flags(flags2); + local_save_flags(flags2); if(jiffies % 3) { printk("ITW %2d %5d: irqsaving (%lx)\n", id, it, flags2); spin_lock_irqsave(&int_test_spin, flags); @@ -484,11 +484,11 @@ spin_lock_irq(&int_test_spin); } - __save_flags(flags2); + local_save_flags(flags2); printk("ITW %2d %5d: locked, sv_waiting (%lx).\n", id, it, flags2); sv_wait(&int_test_sv, 0, 0); - __save_flags(flags2); + local_save_flags(flags2); printk("ITW %2d %5d: wait finished (%lx), pausing\n", id, it, flags2); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(jiffies & 0xf); diff -Nru a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c --- a/arch/m68k/amiga/config.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/amiga/config.c Wed Jul 24 14:03:35 2002 @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef CONFIG_ZORRO #include #endif @@ -110,9 +111,9 @@ #endif static struct console amiga_console_driver = { - name: "debug", - flags: CON_PRINTBUFFER, - index: -1, + .name = "debug", + .flags = CON_PRINTBUFFER, + .index = -1, }; #ifdef CONFIG_MAGIC_SYSRQ @@ -127,8 +128,6 @@ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif -extern void (*kd_mksound)(unsigned int, unsigned int); - /* * Motherboard Resources present in all Amiga models @@ -137,10 +136,10 @@ static struct { struct resource _ciab, _ciaa, _custom, _kickstart; } mb_resources = { - _ciab: { "CIA B", 0x00bfd000, 0x00bfdfff }, - _ciaa: { "CIA A", 0x00bfe000, 0x00bfefff }, - _custom: { "Custom I/O", 0x00dff000, 0x00dfffff }, - _kickstart: { "Kickstart ROM", 0x00f80000, 0x00ffffff } + ._ciab = { "CIA B", 0x00bfd000, 0x00bfdfff }, + ._ciaa = { "CIA A", 0x00bfe000, 0x00bfefff }, + ._custom = { "Custom I/O", 0x00dff000, 0x00dfffff }, + ._kickstart = { "Kickstart ROM", 0x00f80000, 0x00ffffff } }; static struct resource rtc_resource = { @@ -389,10 +388,11 @@ request_resource(&iomem_resource, &((struct resource *)&mb_resources)[i]); mach_sched_init = amiga_sched_init; +#ifdef CONFIG_VT mach_keyb_init = amiga_keyb_init; mach_kbdrate = amiga_kbdrate; mach_kbd_translate = amiga_kbd_translate; - SYSRQ_KEY = 0xff; +#endif mach_init_IRQ = amiga_init_IRQ; mach_default_handler = &amiga_default_handler; mach_request_irq = amiga_request_irq; @@ -432,8 +432,11 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif +#ifdef CONFIG_VT kd_mksound = amiga_mksound; +#endif #ifdef CONFIG_MAGIC_SYSRQ + SYSRQ_KEY = 0xff; mach_sysrq_key = 0x5f; /* HELP */ mach_sysrq_shift_state = 0x03; /* SHIFT+ALTGR */ mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */ diff -Nru a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c --- a/arch/m68k/apollo/config.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/apollo/config.c Wed Jul 24 14:03:37 2002 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,6 @@ extern void dn_dummy_waitbut(void); extern struct fb_info *dn_fb_init(long *); extern void dn_dummy_debug_init(void); -extern void (*kd_mksound)(unsigned int, unsigned int); extern void dn_dummy_video_setup(char *,int *); extern void dn_process_int(int irq, struct pt_regs *fp); #ifdef CONFIG_HEARTBEAT @@ -165,8 +165,10 @@ dn_setup_model(); mach_sched_init=dn_sched_init; /* */ +#ifdef CONFIG_VT mach_keyb_init=dn_keyb_init; mach_kbdrate=dn_dummy_kbdrate; +#endif mach_init_IRQ=dn_init_IRQ; mach_default_handler=NULL; mach_request_irq = dn_request_irq; @@ -187,7 +189,9 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif +#ifdef CONFIG_VT kd_mksound = dn_mksound; +#endif #ifdef CONFIG_HEARTBEAT mach_heartbeat = dn_heartbeat; #endif diff -Nru a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c --- a/arch/m68k/apollo/dn_ints.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/apollo/dn_ints.c Wed Jul 24 14:03:38 2002 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -9,14 +10,10 @@ #include #include #include +#include static irq_handler_t dn_irqs[16]; -extern void write_keyb_cmd(u_short length, u_char *cmd); -static char BellOnCommand[] = { 0xFF, 0x21, 0x81 }, - BellOffCommand[] = { 0xFF, 0x21, 0x82 }; - -extern void dn_serial_print (const char *str); void dn_process_int(int irq, struct pt_regs *fp) { @@ -120,6 +117,11 @@ } +#ifdef CONFIG_VT +extern void write_keyb_cmd(u_short length, u_char *cmd); +static char BellOnCommand[] = { 0xFF, 0x21, 0x81 }, + BellOffCommand[] = { 0xFF, 0x21, 0x82 }; + static void dn_nosound (unsigned long ignored) { write_keyb_cmd(sizeof(BellOffCommand),BellOffCommand); @@ -141,6 +143,8 @@ else write_keyb_cmd(sizeof(BellOffCommand),BellOffCommand); } +#endif /* CONFIG_VT */ + void dn_dummy_video_setup(char *options,int *ints) { diff -Nru a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile --- a/arch/m68k/atari/Makefile Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/atari/Makefile Wed Jul 24 14:03:36 2002 @@ -11,10 +11,12 @@ export-objs := atari_ksyms.o -obj-y := config.o time.o debug.o atakeyb.o ataints.o stdma.o \ - atasound.o joystick.o stram.o atari_ksyms.o +obj-y := config.o time.o debug.o ataints.o stdma.o \ + atasound.o stram.o atari_ksyms.o -ifdef CONFIG_PCI +obj-$(CONFIG_VT) += atakeyb.o joystick.o + +ifeq ($(CONFIG_PCI),y) obj-$(CONFIG_HADES) += hades-pci.o endif diff -Nru a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c --- a/arch/m68k/atari/ataints.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/atari/ataints.c Wed Jul 24 14:03:36 2002 @@ -622,22 +622,22 @@ if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt) continue; if (i < STMFP_SOURCE_BASE) - seq_printf(p,, "auto %2d: %10u ", + seq_printf(p, "auto %2d: %10u ", i, kstat.irqs[0][i]); else - seq_printf(p,, "vec $%02x: %10u ", + seq_printf(p, "vec $%02x: %10u ", IRQ_SOURCE_TO_VECTOR(i), kstat.irqs[0][i]); if (irq_handler[i].handler != atari_call_irq_list) { - seq_printf(p,, "%s\n", irq_param[i].devname); + seq_printf(p, "%s\n", irq_param[i].devname); } else { - irq_node_t *p; - for( p = (irq_node_t *)irq_handler[i].dev_id; p; p = p->next ) { - seq_printf(p,, "%s\n", p->devname); - if (p->next) - seq_puts(p,, " " ); + irq_node_t *n; + for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) { + seq_printf(p, "%s\n", n->devname); + if (n->next) + seq_puts(p, " " ); } } } diff -Nru a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c --- a/arch/m68k/atari/config.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/atari/config.c Wed Jul 24 14:03:36 2002 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -100,7 +101,6 @@ "0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ #endif -extern void (*kd_mksound)(unsigned int, unsigned int); /* I've moved hwreg_present() and hwreg_present_bywrite() out into * mm/hwtest.c, to avoid having multiple copies of the same routine @@ -254,13 +254,12 @@ to 4GB. */ mach_sched_init = atari_sched_init; +#ifdef CONFIG_VT mach_keyb_init = atari_keyb_init; mach_kbdrate = atari_kbdrate; mach_kbd_translate = atari_kbd_translate; -#ifdef CONFIG_MAGIC_SYSRQ - SYSRQ_KEY = 0xff; -#endif mach_kbd_leds = atari_kbd_leds; +#endif mach_init_IRQ = atari_init_IRQ; mach_request_irq = atari_request_irq; mach_free_irq = atari_free_irq; @@ -278,8 +277,11 @@ conswitchp = &dummy_con; #endif mach_max_dma_address = 0xffffff; +#ifdef CONFIG_VT kd_mksound = atari_mksound; +#endif #ifdef CONFIG_MAGIC_SYSRQ + SYSRQ_KEY = 0xff; mach_sysrq_key = 98; /* HELP */ mach_sysrq_shift_state = 8; /* Alt */ mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */ diff -Nru a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c --- a/arch/m68k/atari/debug.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/atari/debug.c Wed Jul 24 14:03:37 2002 @@ -31,9 +31,9 @@ int atari_SCC_reset_done = 0; static struct console atari_console_driver = { - name: "debug", - flags: CON_PRINTBUFFER, - index: -1, + .name = "debug", + .flags = CON_PRINTBUFFER, + .index = -1, }; diff -Nru a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c --- a/arch/m68k/atari/hades-pci.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/atari/hades-pci.c Wed Jul 24 14:03:35 2002 @@ -334,12 +334,12 @@ } static struct pci_ops hades_pci_ops = { - read_byte: hades_read_config_byte - read_word: hades_read_config_word - read_dword: hades_read_config_dword - write_byte: hades_write_config_byte - write_word: hades_write_config_word - write_dword: hades_write_config_dword + .read_byte = hades_read_config_byte, + .read_word = hades_read_config_word, + .read_dword = hades_read_config_dword, + .write_byte = hades_write_config_byte, + .write_word = hades_write_config_word, + .write_dword = hades_write_config_dword }; /* diff -Nru a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c --- a/arch/m68k/atari/joystick.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/atari/joystick.c Wed Jul 24 14:03:35 2002 @@ -22,8 +22,8 @@ #define MAJOR_NR JOYSTICK_MAJOR #define ANALOG_JOY(n) (!(n & 0x80)) -#define DIGITAL_JOY(n) (n & 0x80) -#define DEVICE_NR(n) (MINOR(n) & 0x7f) +#define DIGITAL_JOY(n) (minor(n) & 0x80) +#define DEVICE_NR(n) (minor(n) & 0x7f) static struct joystick_status joystick[2]; @@ -120,11 +120,11 @@ } struct file_operations atari_joystick_fops = { - read: read_joystick, - write: write_joystick, - poll: joystick_poll, - open: open_joystick, - release: release_joystick, + .read = read_joystick, + .write = write_joystick, + .poll = joystick_poll, + .open = open_joystick, + .release = release_joystick, }; int __init atari_joystick_init(void) diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/atari/stram.c Wed Jul 24 14:03:36 2002 @@ -1044,8 +1044,8 @@ static struct block_device_operations stram_fops = { - open: stram_open, - release: stram_release, + .open = stram_open, + .release = stram_release, }; int __init stram_device_init(void) diff -Nru a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c --- a/arch/m68k/bvme6000/config.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/bvme6000/config.c Wed Jul 24 14:03:35 2002 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,6 @@ extern unsigned long bvme6000_gettimeoffset (void); extern int bvme6000_hwclk (int, struct rtc_time *); extern int bvme6000_set_clock_mmss (unsigned long); -extern void bvme6000_check_partition (struct gendisk *hd, unsigned int dev); extern void bvme6000_mksound( unsigned int count, unsigned int ticks ); extern void bvme6000_reset (void); extern void bvme6000_waitbut(void); @@ -133,8 +133,10 @@ mach_max_dma_address = 0xffffffff; mach_sched_init = bvme6000_sched_init; +#ifdef CONFIG_VT mach_keyb_init = bvme6000_keyb_init; mach_kbdrate = bvme6000_kbdrate; +#endif mach_init_IRQ = bvme6000_init_IRQ; mach_gettimeoffset = bvme6000_gettimeoffset; mach_hwclk = bvme6000_hwclk; diff -Nru a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c --- a/arch/m68k/bvme6000/rtc.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/bvme6000/rtc.c Wed Jul 24 14:03:35 2002 @@ -161,9 +161,9 @@ */ static struct file_operations rtc_fops = { - ioctl: rtc_ioctl, - open: rtc_open, - release: rtc_release, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, }; static struct miscdevice rtc_dev= diff -Nru a/arch/m68k/config.in b/arch/m68k/config.in --- a/arch/m68k/config.in Wed Jul 24 14:03:39 2002 +++ b/arch/m68k/config.in Wed Jul 24 14:03:39 2002 @@ -374,11 +374,9 @@ bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 fi -if [ "$CONFIG_VME" = "n" ]; then - define_bool CONFIG_VT y - if [ "$CONFIG_VT" = "y" ]; then - bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE - fi +bool 'Virtual terminal' CONFIG_VT +if [ "$CONFIG_VT" = "y" ]; then + bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE fi if [ "$CONFIG_ATARI" = "y" ]; then @@ -391,7 +389,7 @@ define_bool CONFIG_BUSMOUSE y fi fi -if [ "$CONFIG_ATARI" = "y" ]; then +if [ "$CONFIG_ATARI" = "y" -a "$CONFIG_VT" = "y" ]; then tristate 'Atari mouse support' CONFIG_ATARIMOUSE if [ "$CONFIG_ATARIMOUSE" != "n" ]; then define_bool CONFIG_BUSMOUSE y @@ -413,16 +411,16 @@ if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL fi + tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 + fi fi if [ "$CONFIG_PARPORT" = "n" ]; then if [ "$CONFIG_ZORRO" = "y" ]; then tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT dep_tristate ' GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT dep_tristate ' GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT - tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 - fi fi fi if [ "$CONFIG_MAC" = "y" ]; then @@ -465,21 +463,7 @@ define_bool CONFIG_SUN_MOUSE n define_bool CONFIG_SBUS n fi - -if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ - "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \ - "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" ]; then - if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \ - "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \ - "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ - "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \ - "$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" -o \ - "$CONFIG_SERIAL" = "y" ]; then - bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE - fi -fi if [ "$CONFIG_VME" = "y" ]; then - define_bool CONFIG_SERIAL_CONSOLE y if [ "$CONFIG_MVME147" = "y" ]; then bool 'SCC support for MVME147 serial ports' CONFIG_MVME147_SCC fi @@ -493,10 +477,24 @@ fi if [ "$CONFIG_APOLLO" = "y" ]; then bool 'Support for DN serial port (dummy)' CONFIG_DN_SERIAL - bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE - define_tristate CONFIG_SERIAL $CONFIG_DN_SERIAL fi + +if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \ + "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \ + "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" -o \ + "$CONFIG_VME" = "y" -o "$CONFIG_APOLLO" = "y" ]; then + if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \ + "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \ + "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \ + "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \ + "$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" -o \ + "$CONFIG_SERIAL" = "y" -o "$CONFIG_MVME147_SCC" = "y" -o \ + "$CONFIG_SERIAL167" = "y" -o "$CONFIG_MVME162_SCC" = "y" -o \ + "$CONFIG_BVME6000_SCC" = "y" -o "$CONFIG_DN_SERIAL" = "y" ]; then + bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE + fi +fi bool 'Support for user serial device modules' CONFIG_USERIAL bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then @@ -530,7 +528,7 @@ source fs/Config.in -if [ "$CONFIG_VME" = "n" ]; then +if [ "$CONFIG_VT" = "y" ]; then mainmenu_option next_comment comment 'Console drivers' source drivers/video/Config.in diff -Nru a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S --- a/arch/m68k/fpsp040/skeleton.S Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/fpsp040/skeleton.S Wed Jul 24 14:03:36 2002 @@ -381,9 +381,9 @@ .Lnotkern: SAVE_ALL_INT GET_CURRENT(%d0) - tstl %curptr@(TASK_NEEDRESCHED) + tstb %curptr@(TASK_NEEDRESCHED) jne ret_from_exception | deliver signals, - | reschedule etc.. + | reschedule etc.. RESTORE_ALL | diff -Nru a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c --- a/arch/m68k/hp300/config.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/hp300/config.c Wed Jul 24 14:03:35 2002 @@ -29,10 +29,9 @@ #ifdef CONFIG_VT extern int hp300_keyb_init(void); -#else -/* Dummy function for when there is no keyboard. */ -int __init hp300_keyb_init(void) +static int hp300_kbdrate(struct kbd_repeat *k) { + return 0; } #endif @@ -46,15 +45,6 @@ } #endif -static int hp300_kbdrate(struct kbd_repeat *k) -{ - return 0; -} - -static void hp300_kbd_leds(unsigned int leds) -{ -} - static void hp300_get_model(char *model) { strcpy(model, "HP9000/300"); @@ -63,9 +53,10 @@ void __init config_hp300(void) { mach_sched_init = hp300_sched_init; +#ifdef CONFIG_VT mach_keyb_init = hp300_keyb_init; mach_kbdrate = hp300_kbdrate; - mach_kbd_leds = hp300_kbd_leds; +#endif mach_init_IRQ = hp300_init_IRQ; mach_request_irq = hp300_request_irq; mach_free_irq = hp300_free_irq; diff -Nru a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c --- a/arch/m68k/hp300/ints.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/hp300/ints.c Wed Jul 24 14:03:36 2002 @@ -22,6 +22,7 @@ #include #include #include +#include #include "ints.h" /* Each ipl has a linked list of interrupt service routines. @@ -142,7 +143,9 @@ } /* remove the entry after t: */ t->next->flags = IRQ_FLG_STD; - t->next->dev_id = t->next->devname = t->next->handler = NULL; + t->next->dev_id = NULL; + t->next->devname = NULL; + t->next->handler = NULL; t->next = t->next->next; spin_unlock_irqrestore(&irqlist_lock, flags); diff -Nru a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S --- a/arch/m68k/ifpsp060/iskeleton.S Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/ifpsp060/iskeleton.S Wed Jul 24 14:03:36 2002 @@ -75,7 +75,7 @@ .Lnotkern: SAVE_ALL_INT GET_CURRENT(%d0) - tstl %curptr@(TASK_NEEDRESCHED) + tstb %curptr@(TASK_NEEDRESCHED) jne ret_from_exception | deliver signals, | reschedule etc.. RESTORE_ALL diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S --- a/arch/m68k/kernel/entry.S Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/kernel/entry.S Wed Jul 24 14:03:35 2002 @@ -68,21 +68,11 @@ addql #4,%sp jra ret_from_exception -ENTRY(reschedule) - | save top of frame - movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - - pea ret_from_exception - jmp schedule - - | After a fork we jump here directly from resume, - | so that %d1 contains the previous task - | Theoretically only needed on SMP, but let's watch - | what happens in schedule_tail() in future... + | schedule_tail is only used with CONFIG_SMP ENTRY(ret_from_fork) - movel %d1,%sp@- +#ifdef CONFIG_SMP jsr schedule_tail - addql #4,%sp +#endif jra ret_from_exception badsys: @@ -128,38 +118,54 @@ | save top of frame movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - btst #PT_TRACESYS_BIT,%curptr@(TASK_PTRACE+PT_TRACESYS_OFF) + tstb %curptr@(TASK_SYSCALL_TRACE) jne do_trace cmpl #NR_syscalls,%d0 jcc badsys jbsr @(sys_call_table,%d0:l:4)@(0) movel %d0,%sp@(PT_D0) | save the return value + |oriw #0x0700,%sr + movel %curptr@(TASK_WORK),%d0 + jne syscall_exit_work +1: RESTORE_ALL + +syscall_exit_work: + btst #5,%sp@(PT_SR) | check if returning to kernel + bnes 1b | if so, skip resched, signals + tstw %d0 + jeq do_signal_return + tstb %d0 + jne do_delayed_trace + + pea resume_userspace + jmp schedule + ret_from_exception: btst #5,%sp@(PT_SR) | check if returning to kernel - bnes 2f | if so, skip resched, signals + bnes 1f | if so, skip resched, signals | only allow interrupts when we are really the last one on the | kernel stack, otherwise stack overflow can occur during | heavy interrupt load andw #ALLOWINT,%sr - tstl %curptr@(TASK_NEEDRESCHED) - jne reschedule -#if 0 - cmpl #task,%curptr | task[0] cannot have signals - jeq 2f -#endif - | check for delayed trace - bclr #PT_DTRACE_BIT,%curptr@(TASK_PTRACE+PT_DTRACE_OFF) - jne do_delayed_trace -5: - tstl %curptr@(TASK_STATE) | state - jne reschedule - - tstl %curptr@(TASK_SIGPENDING) - jne Lsignal_return -2: RESTORE_ALL -Lsignal_return: +resume_userspace: + movel %curptr@(TASK_WORK),%d0 + lsrl #8,%d0 + jne exit_work +1: RESTORE_ALL + +exit_work: + | save top of frame + movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) + tstb %d0 + jeq do_signal_return + + pea resume_userspace + jmp schedule + +do_signal_return: + |andw #ALLOWINT,%sr subql #4,%sp | dummy return address SAVE_SWITCH_STACK pea %sp@(SWITCH_STACK_SIZE) @@ -168,7 +174,7 @@ addql #8,%sp RESTORE_SWITCH_STACK addql #4,%sp - RESTORE_ALL + jbra resume_userspace do_delayed_trace: bclr #7,%sp@(PT_SR) | clear trace bit in SR @@ -178,13 +184,13 @@ jbsr send_sig addql #8,%sp addql #4,%sp - jra 5b + jbra resume_userspace #if 0 #if CONFIG_AMIGA ami_inthandler: - addql #1,irq_stat+8 | local_irq_count + addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT SAVE_ALL_INT GET_CURRENT(%d0) @@ -216,14 +222,14 @@ inthandler: SAVE_ALL_INT GET_CURRENT(%d0) - addql #1,irq_stat+8 | local_irq_count + addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT | put exception # in d0 bfextu %sp@(PT_VECTOR){#4,#10},%d0 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack #if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) - btstb #4,0xff000000 | Q40 floppy needs very special treatment ... + btstb #4,0xff000000 | Q40 floppy needs very special treatment ... jbeq 1f btstb #3,0xff000004 jbeq 1f @@ -231,11 +237,11 @@ jbra 3f 1: #endif - jbsr process_int| process the IRQ + jbsr process_int | process the IRQ 3: addql #8,%sp | pop parameters off stack ret_from_interrupt: - subql #1,irq_stat+8 | local_irq_count + subql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT jeq 1f 2: RESTORE_ALL @@ -248,11 +254,8 @@ jhi 2b #endif /* check if we need to do software interrupts */ - - movel irq_stat,%d0 | softirq_active - andl irq_stat+4,%d0 | softirq_mask + tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING jeq ret_from_exception - pea ret_from_exception jra do_softirq @@ -460,7 +463,7 @@ .long sys_ni_syscall /* old gtty syscall holder */ .long sys_access .long sys_nice - .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ .long sys_sync .long sys_kill .long sys_rename @@ -477,7 +480,7 @@ .long sys_geteuid16 .long sys_getegid16 /* 50 */ .long sys_acct - .long sys_umount /* recycled never used phys() */ + .long sys_umount /* recycled never used phys() */ .long sys_ni_syscall /* old lock syscall holder */ .long sys_ioctl .long sys_fcntl /* 55 */ @@ -535,10 +538,10 @@ .long sys_newlstat .long sys_newfstat .long sys_ni_syscall - .long sys_ni_syscall /* iopl for i386 */ /* 110 */ + .long sys_ni_syscall /* 110 */ /* iopl for i386 */ .long sys_vhangup - .long sys_ni_syscall /* obsolete idle() syscall */ - .long sys_ni_syscall /* vm86old for i386 */ + .long sys_ni_syscall /* obsolete idle() syscall */ + .long sys_ni_syscall /* vm86old for i386 */ .long sys_wait4 .long sys_swapoff /* 115 */ .long sys_sysinfo @@ -548,7 +551,7 @@ .long sys_clone /* 120 */ .long sys_setdomainname .long sys_newuname - .long sys_cacheflush /* modify_ldt for i386 */ + .long sys_cacheflush /* modify_ldt for i386 */ .long sys_adjtimex .long sys_mprotect /* 125 */ .long sys_sigprocmask @@ -562,7 +565,7 @@ .long sys_bdflush .long sys_sysfs /* 135 */ .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ + .long sys_ni_syscall /* for afs_syscall */ .long sys_setfsuid16 .long sys_setfsgid16 .long sys_llseek /* 140 */ @@ -580,7 +583,7 @@ .long sys_mlockall .long sys_munlockall .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ + .long sys_sched_getparam /* 155 */ .long sys_sched_setscheduler .long sys_sched_getscheduler .long sys_sched_yield @@ -613,8 +616,8 @@ .long sys_capset /* 185 */ .long sys_sigaltstack .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ + .long sys_ni_syscall /* streams1 */ + .long sys_ni_syscall /* streams2 */ .long sys_vfork /* 190 */ .long sys_getrlimit .long sys_mmap2 @@ -642,12 +645,25 @@ .long sys_setgid .long sys_setfsuid /* 215 */ .long sys_setfsgid - .long sys_ni_syscall + .long sys_pivot_root .long sys_ni_syscall .long sys_ni_syscall .long sys_getdents64 /* 220 */ .long sys_gettid .long sys_tkill + .long sys_setxattr + .long sys_lsetxattr + .long sys_fsetxattr /* 225 */ + .long sys_getxattr + .long sys_lgetxattr + .long sys_fgetxattr + .long sys_listxattr + .long sys_llistxattr /* 230 */ + .long sys_flistxattr + .long sys_removexattr + .long sys_lremovexattr + .long sys_fremovexattr + .long sys_futex /* 235 */ .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff -Nru a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S --- a/arch/m68k/kernel/head.S Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/kernel/head.S Wed Jul 24 14:03:38 2002 @@ -312,6 +312,9 @@ #ifdef CONFIG_Q40 .globl q40_mem_cptr #endif +#ifdef CONFIG_HP300 +.globl hp300_phys_ram_base +#endif CPUTYPE_040 = 1 /* indicates an 040 */ CPUTYPE_060 = 2 /* indicates an 060 */ @@ -596,6 +599,64 @@ __INIT ENTRY(__start) +#ifdef CONFIG_HP300 +/* This is a hack. The HP NetBSD bootloader loads us at an arbitrary + address (apparently 0xff002000 in practice) which is not good if we need + to be able to map this to VA 0x1000. We could do it with pagetables but + a better solution seems to be to relocate the kernel in physical memory + before we start. + + So, we copy the entire kernel image (code+data+bss) down to the 16MB + boundary that marks the start of RAM. This is slightly tricky because + we must not overwrite the copying code itself. :-) */ + +/* 15/5/98. The start address of physical RAM changes depending on how much + RAM is present. This is actually a blessing in disguise as it provides + a way for us to work out the RAM size rather than hardwiring it. */ + + lea %pc@(_start),%a0 + movel %a0,%d6 + and #0xffff0000, %d6 + lea %pc@(hp300_phys_ram_base),%a0 + movel %d6, %a0@ + movel %pc@(L(custom)),%a3 + moveb #0xfe,%d7 + moveb %d7,%a3@(0x1ffff) + lea %pc@(Lcopystart),%a0 + lea %pc@(Lcopyend),%a1 + movel %d6,%a2 /* Start of physical RAM */ +1: moveb %a0@+,%d0 + moveb %d0,%a2@+ + cmpl %a0,%a1 + jbne 1b + movel %d6,%a2 + moveb #0xfd,%d7 + moveb %d7,%a3@(0x1ffff) + lea %pc@(_stext),%a0 + lea %pc@(_end),%a1 + jmp %a2@ + +Lcopystart: + moveb #0xf7,%d7 + moveb %d7,%a3@(0x1ffff) + movel %d6,%a2 /* Start of kernel */ + add #0x1000,%a2 +1: moveb %a0@+,%d0 + moveb %d0,%a2@+ + cmpl %a0,%a1 + jbne 1b + moveb #0,%d7 + moveb %d7,%a3@(0x1ffff) + movel %d6,%a0 + addl #Lstart1,%a0 + jmp %a0@ +Lcopyend: + +Lstart1: + moveb #0x3f,%d7 + moveb %d7,%a3@(0x1ffff) +#endif /* CONFIG_HP300 */ + /* * Setup initial stack pointer */ @@ -605,6 +666,7 @@ * Record the CPU and machine type. */ +#ifndef CONFIG_HP300 get_bi_record BI_MACHTYPE lea %pc@(m68k_machtype),%a1 movel %a0@,%a1@ @@ -620,6 +682,23 @@ get_bi_record BI_CPUTYPE lea %pc@(m68k_cputype),%a1 movel %a0@,%a1@ +#else /* CONFIG_HP300 */ + /* FIXME HP300 doesn't use bootinfo yet */ + movel #MACH_HP300,%d4 + lea %pc@(m68k_machtype),%a0 + movel %d4,%a0@ + movel #FPU_68881,%d0 + lea %pc@(m68k_fputype),%a0 + movel %d0,%a0@ + movel #MMU_68030,%d0 + lea %pc@(m68k_mmutype),%a0 + movel %d0,%a0@ + movel #CPU_68030,%d0 + lea %pc@(m68k_cputype),%a0 + movel %d0,%a0@ + + leds(0x1) +#endif /* CONFIG_HP300 */ #ifdef CONFIG_MAC /* @@ -893,6 +972,9 @@ putc '\n' putc 'A' +#ifdef CONFIG_HP300 + leds(0x2) +#endif /* CONFIG_HP300 */ dputn %pc@(L(cputype)) dputn %pc@(m68k_supervisor_cachemode) dputn %pc@(m68k_pgtable_cachemode) @@ -1461,8 +1543,8 @@ /* * Setup initial stack pointer */ - lea init_task_union,%curptr - lea 0x2000(%curptr),%sp + lea init_task,%curptr + lea init_thread_union+THREAD_SIZE,%sp putc 'K' @@ -1490,6 +1572,7 @@ movel ARG1,%d0 lea %pc@(_end),%a0 +#ifndef CONFIG_HP300 1: tstw %a0@(BIR_TAG) jeq 3f cmpw %a0@(BIR_TAG),%d0 @@ -1503,6 +1586,7 @@ 3: moveq #-1,%d0 lea %a0@(BIR_SIZE),%a0 4: +#endif /* CONFIG_HP300 */ func_return get_bi_record @@ -3270,14 +3354,16 @@ /* Calculate font size */ -#if defined(FONT_8x8) - lea %pc@(font_vga_8x8), %a0 -#elif defined(FONT_8x16) +#if defined(FONT_8x8) && defined(CONFIG_FONT_8x8) + lea %pc@(font_vga_8x8),%a0 +#elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16) lea %pc@(font_vga_8x16),%a0 -#elif defined(FONT_6x11) +#elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11) lea %pc@(font_vga_6x11),%a0 -#else /* (FONT_8x8) default */ - lea %pc@(font_vga_8x8), %a0 +#elif defined(CONFIG_FONT_8x8) /* default */ + lea %pc@(font_vga_8x8),%a0 +#else /* no compiled-in font */ + lea 0,%a0 #endif /* @@ -3286,6 +3372,8 @@ */ lea %pc@(L(console_font)),%a1 movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in Lconsole_font */ + tstl %a0 + jeq 1f /* * Calculate global maxs @@ -3313,7 +3401,7 @@ /* * Initialization is complete */ - moveml %sp@+,%a0-%a4/%d0-%d7 +1: moveml %sp@+,%a0-%a4/%d0-%d7 rts L(console_put_stats): @@ -3399,6 +3487,8 @@ lea %pc@(L(mac_rowbytes)),%a0 movel %a0@,%d5 movel %pc@(L(console_font)),%a0 + tstl %a0 + jeq 1f mulul %a0@(FBCON_FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */ addal %d5,%a2 @@ -3453,13 +3543,15 @@ movel %d0,%a1@+ dbra %d6,console_scroll_clear_loop - moveml %sp@+,%a0-%a4/%d0-%d7 +1: moveml %sp@+,%a0-%a4/%d0-%d7 rts func_start console_putc,%a0/%a1/%d0-%d7 is_not_mac(console_exit) + tstl %pc@(L(console_font)) + jeq console_exit /* Output character in d7 on console. */ @@ -3731,7 +3823,12 @@ __INITDATA .align 4 -#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || defined(CONFIG_HP300) +#ifdef CONFIG_HP300 +hp300_phys_ram_base: +#endif + +#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \ + defined(CONFIG_HP300) || defined(CONFIG_APOLLO) L(custom): L(iobase): .long 0 @@ -3822,8 +3919,6 @@ LSRB0 = 0x10412 LTHRB0 = 0x10416 LCPUCTRL = 0x10100 -L(iobase): - .long 0 #endif __FINIT diff -Nru a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c --- a/arch/m68k/kernel/m68k_defs.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/kernel/m68k_defs.c Wed Jul 24 14:03:35 2002 @@ -25,8 +25,11 @@ DEFINE(TASK_STATE, offsetof(struct task_struct, state)); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); -#error DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, work.sigpending)); -#error DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, work.need_resched)); + 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)); @@ -65,6 +68,12 @@ /* 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)); + DEFINE(CPUSTAT_LOCAL_IRQ_COUNT, offsetof(irq_cpustat_t, __local_irq_count)); + DEFINE(CPUSTAT_LOCAL_BH_COUNT, offsetof(irq_cpustat_t, __local_bh_count)); + DEFINE(CPUSTAT_SYSCALL_COUNT, offsetof(irq_cpustat_t, __syscall_count)); /* offsets into the bi_record struct */ DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c --- a/arch/m68k/kernel/process.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/kernel/process.c Wed Jul 24 14:03:38 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ #include /* - * Initial task structure. Make this a per-architecture thing, + * Initial task/thread structure. Make this a per-architecture thing, * because different architectures tend to have different * alignment requirements and potentially different initial * setup. @@ -43,14 +44,34 @@ static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); -union task_union init_task_union -__attribute__((section("init_task"), aligned(THREAD_SIZE))) - = { task: INIT_TASK(init_task_union.task) }; +union thread_union init_thread_union +__attribute__((section(".data.init_task"), aligned(THREAD_SIZE))) + = { INIT_THREAD_INFO(init_task) }; + +/* initial task structure */ +struct task_struct init_task = INIT_TASK(init_task); + asmlinkage void ret_from_fork(void); /* + * Return saved PC from a blocked thread + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + extern void scheduling_functions_start_here(void); + extern void scheduling_functions_end_here(void); + struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; + /* Check whether the thread is blocked in resume() */ + if (sw->retpc > (unsigned long)scheduling_functions_start_here && + sw->retpc < (unsigned long)scheduling_functions_end_here) + return ((unsigned long *)sw->a6)[1]; + else + return sw->retpc; +} + +/* * The idle loop on an m68k.. */ void default_idle(void) @@ -133,23 +154,26 @@ register long retval __asm__ ("d0"); register long clone_arg __asm__ ("d1") = flags | CLONE_VM; + retval = __NR_clone; __asm__ __volatile__ ("clrl %%d2\n\t" "trap #0\n\t" /* Linux/m68k system call */ "tstl %0\n\t" /* child or parent */ "jne 1f\n\t" /* parent - jump */ "lea %%sp@(%c7),%6\n\t" /* reload current */ + "movel %6@,%6\n\t" "movel %3,%%sp@-\n\t" /* push argument */ "jsr %4@\n\t" /* call fn */ "movel %0,%%d1\n\t" /* pass exit value */ - "movel %2,%0\n\t" /* exit */ + "movel %2,%%d0\n\t" /* exit */ "trap #0\n" "1:" - : "=d" (retval) - : "0" (__NR_clone), "i" (__NR_exit), + : "+d" (retval) + : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), "i" (-THREAD_SIZE) - : "d0", "d2"); + : "d2"); + pid = retval; } @@ -366,7 +390,7 @@ if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)p; + stack_page = (unsigned long)(p->thread_info); fp = ((struct switch_stack *)p->thread.ksp)->a6; do { if (fp < stack_page+sizeof(struct task_struct) || diff -Nru a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c --- a/arch/m68k/kernel/ptrace.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/kernel/ptrace.c Wed Jul 24 14:03:37 2002 @@ -98,12 +98,13 @@ /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + child->thread.work.delayed_trace = 0; + child->thread.work.syscall_trace = 0; } asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; - unsigned long flags; int ret; lock_kernel(); @@ -243,14 +244,16 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - if (request == PTRACE_SYSCALL) - child->ptrace |= PT_TRACESYS; - else - child->ptrace &= ~PT_TRACESYS; + if (request == PTRACE_SYSCALL) { + child->thread.work.syscall_trace = ~0; + } else { + child->thread.work.syscall_trace = 0; + } child->exit_code = data; /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + child->thread.work.delayed_trace = 0; wake_up_process(child); ret = 0; break; @@ -271,6 +274,7 @@ /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + child->thread.work.delayed_trace = 0; wake_up_process(child); break; } @@ -281,9 +285,10 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->ptrace &= ~PT_TRACESYS; + child->thread.work.syscall_trace = 0; tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); put_reg(child, PT_SR, tmp); + child->thread.work.delayed_trace = 1; child->exit_code = data; /* give it a chance to run. */ @@ -354,7 +359,7 @@ break; } out_tsk: - free_task_struct(child); + put_task_struct(child); out: unlock_kernel(); return ret; @@ -362,8 +367,8 @@ asmlinkage void syscall_trace(void) { - if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) - != (PT_PTRACED|PT_TRACESYS)) + if (!current->thread.work.delayed_trace && + !current->thread.work.syscall_trace) return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; diff -Nru a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c --- a/arch/m68k/kernel/setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/m68k/kernel/setup.c Wed Jul 24 14:03:39 2002 @@ -34,6 +34,7 @@ #endif #ifdef CONFIG_ATARI #include +#include #endif #ifdef CONFIG_SUN3X #include @@ -71,11 +72,12 @@ void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL; /* machine dependent keyboard functions */ +#ifdef CONFIG_VT int (*mach_keyb_init) (void) __initdata = NULL; int (*mach_kbdrate) (struct kbd_repeat *) = NULL; void (*mach_kbd_leds) (unsigned int) = NULL; int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL; -unsigned int SYSRQ_KEY; +#endif /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; @@ -103,13 +105,14 @@ #endif #ifdef CONFIG_MAGIC_SYSRQ +unsigned int SYSRQ_KEY; int mach_sysrq_key = -1; int mach_sysrq_shift_state = 0; int mach_sysrq_shift_mask = 0; char *mach_sysrq_xlate = NULL; #endif -#if defined(CONFIG_ISA) +#if defined(CONFIG_ISA) && defined(MULTI_ISA) int isa_type; int isa_sex; #endif @@ -217,8 +220,20 @@ int i; char *p, *q; - /* The bootinfo is located right after the kernel bss */ - m68k_parse_bootinfo((const struct bi_record *)&_end); + if (!MACH_IS_HP300) { + /* The bootinfo is located right after the kernel bss */ + m68k_parse_bootinfo((const struct bi_record *)&_end); + } else { + /* FIXME HP300 doesn't use bootinfo yet */ + extern unsigned long hp300_phys_ram_base; + unsigned long hp300_mem_size = 0xffffffff-hp300_phys_ram_base; + m68k_cputype = CPU_68030; + m68k_fputype = FPU_68882; + m68k_memory[0].addr = hp300_phys_ram_base; + /* 0.5M fudge factor */ + m68k_memory[0].size = hp300_mem_size-512*1024; + m68k_num_memory++; + } if (CPU_IS_040) m68k_is040or060 = 4; @@ -371,7 +386,7 @@ #ifdef CONFIG_ATARI if (MACH_IS_ATARI) - atari_stram_reserve_pages(availmem); + atari_stram_reserve_pages((void *)availmem); #endif #ifdef CONFIG_SUN3X if (MACH_IS_SUN3X) { @@ -387,7 +402,7 @@ paging_init(); /* set ISA defs early as possible */ -#if defined(CONFIG_ISA) +#if defined(CONFIG_ISA) && defined(MULTI_ISA) #if defined(CONFIG_Q40) if (MACH_IS_Q40) { isa_type = Q40_ISA; @@ -494,10 +509,10 @@ { } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: show_cpuinfo, + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, }; int get_hardware_list(char *buffer) @@ -513,7 +528,6 @@ strcpy(model, "Unknown m68k"); len += sprintf(buffer+len, "Model:\t\t%s\n", model); - len += get_cpuinfo(buffer+len); for (mem = 0, i = 0; i < m68k_num_memory; i++) mem += m68k_memory[i].size; len += sprintf(buffer+len, "System Memory:\t%ldK\n", mem>>10); diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c --- a/arch/m68k/kernel/signal.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/kernel/signal.c Wed Jul 24 14:03:36 2002 @@ -792,10 +792,10 @@ regs->stkadj = fsize; } - err |= __put_user((current->exec_domain - && current->exec_domain->signal_invmap + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap && sig < 32 - ? current->exec_domain->signal_invmap[sig] + ? current_thread_info()->exec_domain->signal_invmap[sig] : sig), &frame->sig); @@ -870,10 +870,10 @@ regs->stkadj = fsize; } - err |= __put_user((current->exec_domain - && current->exec_domain->signal_invmap + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap && sig < 32 - ? current->exec_domain->signal_invmap[sig] + ? current_thread_info()->exec_domain->signal_invmap[sig] : sig), &frame->sig); err |= __put_user(&frame->info, &frame->pinfo); diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c --- a/arch/m68k/kernel/traps.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/kernel/traps.c Wed Jul 24 14:03:38 2002 @@ -224,7 +224,7 @@ unsigned long addr = fp->un.fmt4.effaddr; if (fslw & MMU060_MA) - addr = (addr + 7) & -8; + addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; errorcode = 1; if (fslw & MMU060_DESC_ERR) { @@ -258,16 +258,12 @@ set_fs(MAKE_MM_SEG(wbs)); - asm volatile (".chip 68040"); - if (iswrite) - asm volatile ("ptestw (%0)" : : "a" (addr)); + asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); else - asm volatile ("ptestr (%0)" : : "a" (addr)); + asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); - asm volatile ("movec %%mmusr,%0" : "=r" (mmusr)); - - asm volatile (".chip 68k"); + asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); set_fs(old_fs); @@ -455,6 +451,7 @@ unsigned char buserr_type = sun3_get_buserr (); unsigned long addr, errorcode; unsigned short ssw = fp->un.fmtb.ssw; + extern unsigned long _sun3_map_test_start, _sun3_map_test_end; #if DEBUG if (ssw & (FC | FB)) @@ -494,6 +491,13 @@ printk ("Instruction fault at %#010lx\n", fp->ptregs.pc); if (ssw & DF) { + /* was this fault incurred testing bus mappings? */ + if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && + (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { + send_fault_sig(&fp->ptregs); + return; + } + printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", ssw & RW ? "read" : "write", fp->un.fmtb.daddr, @@ -820,8 +824,9 @@ static inline int kernel_text_address(unsigned long addr) { +#ifdef CONFIG_MODULES struct module *mod; - int retval = 0; +#endif extern char _stext, _etext; if (addr >= (unsigned long) &_stext && @@ -833,14 +838,12 @@ /* mod_bound tests for addr being inside the vmalloc'ed * module area. Of course it'd be better to test only * for the .text subset... */ - if (mod_bound(addr, 0, mod)) { - retval = 1; - break; - } + if (mod_bound(addr, 0, mod)) + return 1; } #endif - return retval; + return 0; } void show_trace(unsigned long *stack) diff -Nru a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c --- a/arch/m68k/mac/baboon.c Wed Jul 24 14:03:36 2002 +++ b/arch/m68k/mac/baboon.c Wed Jul 24 14:03:36 2002 @@ -19,8 +19,8 @@ #include #include -/* #define DEBUG_BABOON /**/ -/* #define DEBUG_IRQS /**/ +/* #define DEBUG_BABOON */ +/* #define DEBUG_IRQS */ int baboon_present,baboon_active; volatile struct baboon *baboon; diff -Nru a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c --- a/arch/m68k/mac/config.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/mac/config.c Wed Jul 24 14:03:38 2002 @@ -21,6 +21,7 @@ #include /* keyb */ #include +#include #define BOOTINFO_COMPAT_1_0 #include @@ -47,6 +48,8 @@ struct mac_booter_data mac_bi_data = {0,}; int mac_bisize = sizeof mac_bi_data; +struct mac_hw_present mac_hw_present; + /* New m68k bootinfo stuff and videobase */ extern int m68k_num_memory; @@ -75,7 +78,6 @@ extern void psc_init(void); extern void baboon_init(void); -extern void (*kd_mksound)(unsigned int, unsigned int); extern void mac_mksound(unsigned int, unsigned int); extern void nubus_sweep_video(void); @@ -84,8 +86,6 @@ extern void mac_debug_init(void); extern void mac_debugging_long(int, long); -extern void (*kd_mksound)(unsigned int, unsigned int); - extern int mackbd_init_hw(void); extern void mackbd_leds(unsigned int leds); extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode); @@ -206,7 +206,7 @@ if (!MACH_IS_MAC) { printk("ERROR: no Mac, but config_mac() called!! \n"); } - + #ifdef CONFIG_VT #ifdef CONFIG_INPUT_ADBHID mach_keyb_init = mac_hid_init_hw; @@ -227,8 +227,10 @@ mach_keyb_init = mackbd_init_hw; mach_kbd_leds = mackbd_leds; mach_kbd_translate = mackbd_translate; +#ifdef CONFIG_MAGIC_SYSRQ mach_sysrq_xlate = mackbd_sysrq_xlate; SYSRQ_KEY = 0x69; +#endif /* CONFIG_MAGIC_SYSRQ */ #endif /* CONFIG_INPUT_ADBHID */ #endif /* CONFIG_VT */ @@ -253,12 +255,16 @@ mach_reset = mac_reset; mach_halt = mac_poweroff; mach_power_off = mac_poweroff; +#ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; +#endif mach_max_dma_address = 0xffffffff; #if 0 mach_debug_init = mac_debug_init; #endif +#ifdef CONFIG_VT kd_mksound = mac_mksound; +#endif #ifdef CONFIG_HEARTBEAT #if 0 mach_heartbeat = mac_heartbeat; diff -Nru a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c --- a/arch/m68k/mac/debug.c Wed Jul 24 14:03:39 2002 +++ b/arch/m68k/mac/debug.c Wed Jul 24 14:03:39 2002 @@ -36,7 +36,7 @@ extern unsigned long mac_videodepth; extern unsigned long mac_rowbytes; -extern void mac_serial_print(char *); +extern void mac_serial_print(const char *); #define DEBUG_HEADS #undef DEBUG_SCREEN @@ -137,7 +137,7 @@ * TODO: serial debug code */ -struct SCC +struct mac_SCC { u_char cha_b_ctrl; u_char char_dummy1; @@ -148,7 +148,7 @@ u_char cha_a_data; }; -# define scc (*((volatile struct SCC*)mac_bi_data.sccbase)) +# define scc (*((volatile struct mac_SCC*)mac_bi_data.sccbase)) /* Flag that serial port is already initialized and used */ int mac_SCC_init_done = 0; @@ -159,9 +159,9 @@ static int scc_port = -1; static struct console mac_console_driver = { - name: "debug", - flags: CON_PRINTBUFFER, - index: -1, + .name = "debug", + .flags = CON_PRINTBUFFER, + .index = -1, }; /* @@ -235,20 +235,6 @@ } } -#if defined(CONFIG_SERIAL_CONSOLE) || defined(DEBUG_SERIAL) -int mac_sccb_console_wait_key(struct console *co) -{ - int i; - do { - for( i = uSEC; i > 0; --i ) - barrier(); - } while( !(scc.cha_b_ctrl & 0x01) ); /* wait for rx buf filled */ - for( i = uSEC; i > 0; --i ) - barrier(); - return( scc.cha_b_data ); -} - -#endif /* The following two functions do a quick'n'dirty initialization of the MFP or * SCC serial ports. They're used by the debugging interface, kgdb, and the @@ -390,9 +376,6 @@ /* Mac printer port */ mac_init_scc_port( B9600|CS8, 1 ); mac_console_driver.write = mac_sccb_console_write; -#ifdef CONFIG_SERIAL_CONSOLE - mac_console_driver.wait_key = mac_sccb_console_wait_key; -#endif scc_port = 1; } #endif diff -Nru a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c --- a/arch/m68k/mac/macints.c Wed Jul 24 14:03:39 2002 +++ b/arch/m68k/mac/macints.c Wed Jul 24 14:03:39 2002 @@ -131,6 +131,7 @@ #include #include #include +#include #include diff -Nru a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c --- a/arch/m68k/mac/misc.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/mac/misc.c Wed Jul 24 14:03:38 2002 @@ -229,8 +229,8 @@ do { if (++ct > 10) { printk("via_read_time: couldn't get valid time, " - "last read = 0x%08X and 0x%08X\n", last_result.idata, - result.idata); + "last read = 0x%08lx and 0x%08lx\n", + last_result.idata, result.idata); break; } diff -Nru a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c --- a/arch/m68k/mm/fault.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/mm/fault.c Wed Jul 24 14:03:38 2002 @@ -152,22 +152,25 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ + + survive: fault = handle_mm_fault(mm, vma, address, write); #ifdef DEBUG printk("handle_mm_fault returns %d\n",fault); #endif - if (fault < 0) - goto out_of_memory; - if (!fault) + switch (fault) { + case 1: + current->min_flt++; + break; + case 2: + current->maj_flt++; + break; + case 0: goto bus_err; + default: + goto out_of_memory; + } - /* There seems to be a missing invalidate somewhere in do_no_page. - * Until I found it, this one cures the problem and makes - * 1.2 run on the 68040 (Martin Apel). - */ - #warning should be obsolete now... - if (CPU_IS_040_OR_060) - flush_tlb_page(vma, address); up_read(&mm->mmap_sem); return 0; @@ -176,6 +179,13 @@ * us unable to handle the page fault gracefully. */ out_of_memory: + up_read(&mm->mmap_sem); + if (current->pid == 1) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) do_exit(SIGKILL); diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c --- a/arch/m68k/mm/init.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/mm/init.c Wed Jul 24 14:03:37 2002 @@ -36,17 +36,11 @@ mmu_gather_t mmu_gathers[NR_CPUS]; /* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving an inode - * unused etc.. - * * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -unsigned long empty_zero_page; +void *empty_zero_page; void show_mem(void) { diff -Nru a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c --- a/arch/m68k/mm/memory.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/mm/memory.c Wed Jul 24 14:03:38 2002 @@ -77,14 +77,14 @@ * virtual address space to be noncacheable. */ if (mask == 0) { - unsigned long page; + void *page; ptable_desc *new; - if (!(page = get_free_page (GFP_KERNEL))) + if (!(page = (void *)get_free_page(GFP_KERNEL))) return 0; flush_tlb_kernel_page(page); - nocache_page (page); + nocache_page(page); new = PD_PTABLE(page); PD_MARKBITS(new) = 0xfe; @@ -119,7 +119,7 @@ if (PD_MARKBITS(dp) == 0xff) { /* all tables in page are free, free page */ list_del(dp); - cache_page (page); + cache_page((void *)page); free_page (page); return 1; } else if (ptable_list.next != dp) { @@ -185,10 +185,6 @@ } voff -= m68k_memory[i].size; } while (++i < m68k_num_memory); - - /* As a special case allow `__pa(high_memory)'. */ - if (voff == 0) - return m68k_memory[i-1].addr + m68k_memory[i-1].size; /* As a special case allow `__pa(high_memory)'. */ if (voff == 0) diff -Nru a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c --- a/arch/m68k/mm/motorola.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/mm/motorola.c Wed Jul 24 14:03:38 2002 @@ -52,9 +52,9 @@ ptablep = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); clear_page(ptablep); - __flush_page_to_ram((unsigned long) ptablep); - flush_tlb_kernel_page((unsigned long) ptablep); - nocache_page ((unsigned long)ptablep); + __flush_page_to_ram(ptablep); + flush_tlb_kernel_page(ptablep); + nocache_page(ptablep); return ptablep; } @@ -87,15 +87,15 @@ #endif } - if (((unsigned long)(last_pgtable + PTRS_PER_PMD) & ~PAGE_MASK) == 0) { + last_pgtable += PTRS_PER_PMD; + if (((unsigned long)last_pgtable & ~PAGE_MASK) == 0) { last_pgtable = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); clear_page(last_pgtable); - __flush_page_to_ram((unsigned long)last_pgtable); - flush_tlb_kernel_page((unsigned long)last_pgtable); - nocache_page((unsigned long)last_pgtable); - } else - last_pgtable += PTRS_PER_PMD; + __flush_page_to_ram(last_pgtable); + flush_tlb_kernel_page(last_pgtable); + nocache_page(last_pgtable); + } return last_pgtable; } @@ -262,8 +262,8 @@ * initialize the bad page table and bad page to point * to a couple of allocated pages */ - empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); + empty_zero_page = alloc_bootmem_pages(PAGE_SIZE); + memset(empty_zero_page, 0, PAGE_SIZE); /* * Set up SFC/DFC registers diff -Nru a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c --- a/arch/m68k/mvme147/config.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/mvme147/config.c Wed Jul 24 14:03:37 2002 @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -48,7 +50,6 @@ extern unsigned long mvme147_gettimeoffset (void); extern int mvme147_hwclk (int, struct rtc_time *); extern int mvme147_set_clock_mmss (unsigned long); -extern void mvme147_check_partition (struct gendisk *hd, unsigned int dev); extern void mvme147_reset (void); extern void mvme147_waitbut(void); @@ -101,8 +102,10 @@ { mach_max_dma_address = 0x01000000; mach_sched_init = mvme147_sched_init; +#ifdef CONFIG_VT mach_keyb_init = mvme147_keyb_init; mach_kbdrate = mvme147_kbdrate; +#endif mach_init_IRQ = mvme147_init_IRQ; mach_gettimeoffset = mvme147_gettimeoffset; mach_hwclk = mvme147_hwclk; diff -Nru a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c --- a/arch/m68k/mvme16x/config.c Wed Jul 24 14:03:37 2002 +++ b/arch/m68k/mvme16x/config.c Wed Jul 24 14:03:37 2002 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -52,7 +54,6 @@ extern unsigned long mvme16x_gettimeoffset (void); extern int mvme16x_hwclk (int, struct rtc_time *); extern int mvme16x_set_clock_mmss (unsigned long); -extern void mvme16x_check_partition (struct gendisk *hd, unsigned int dev); extern void mvme16x_mksound( unsigned int count, unsigned int ticks ); extern void mvme16x_reset (void); extern void mvme16x_waitbut(void); @@ -143,13 +144,17 @@ mach_max_dma_address = 0xffffffff; mach_sched_init = mvme16x_sched_init; +#ifdef CONFIG_VT mach_keyb_init = mvme16x_keyb_init; mach_kbdrate = mvme16x_kbdrate; +#endif mach_init_IRQ = mvme16x_init_IRQ; mach_gettimeoffset = mvme16x_gettimeoffset; mach_hwclk = mvme16x_hwclk; mach_set_clock_mmss = mvme16x_set_clock_mmss; +#ifdef CONFIG_VT /* kd_mksound = mvme16x_mksound; */ +#endif mach_reset = mvme16x_reset; mach_free_irq = mvme16x_free_irq; mach_process_int = mvme16x_process_int; diff -Nru a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c --- a/arch/m68k/mvme16x/rtc.c Wed Jul 24 14:03:39 2002 +++ b/arch/m68k/mvme16x/rtc.c Wed Jul 24 14:03:39 2002 @@ -150,9 +150,9 @@ */ static struct file_operations rtc_fops = { - ioctl: rtc_ioctl, - open: rtc_open, - release: rtc_release, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, }; static struct miscdevice rtc_dev= diff -Nru a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c --- a/arch/m68k/q40/config.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/q40/config.c Wed Jul 24 14:03:38 2002 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,6 @@ extern void q40_waitbut(void); void q40_set_vectors (void); -extern void (*kd_mksound)(unsigned int, unsigned int); void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); extern char *saved_command_line; @@ -72,9 +72,9 @@ extern int ql_ticks; static struct console q40_console_driver = { - name: "debug", - flags: CON_PRINTBUFFER, - index: -1, + .name = "debug", + .flags = CON_PRINTBUFFER, + .index = -1, }; @@ -162,42 +162,6 @@ sprintf(model, "Q40"); } -/* pasted code to make parport_pc happy */ -extern __inline__ int __get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} -void *pci_alloc_consistent(void *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - ret = (void *)__get_free_pages(gfp, __get_order(size)); - - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); - } - return ret; -} - -void pci_free_consistent(void *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, __get_order(size)); -} -/* end pasted code */ - - /* No hardware options on Q40? */ static int q40_get_hardware_list(char *buffer) @@ -221,8 +185,10 @@ { mach_sched_init = q40_sched_init; +#ifdef CONFIG_VT mach_keyb_init = q40kbd_init_hw; mach_kbd_translate = q40kbd_translate; +#endif mach_init_IRQ = q40_init_IRQ; mach_gettimeoffset = q40_gettimeoffset; mach_hwclk = q40_hwclk; @@ -238,7 +204,9 @@ mach_default_handler = &q40_sys_default_handler; mach_get_model = q40_get_model; mach_get_hardware_list = q40_get_hardware_list; +#ifdef CONFIG_VT kd_mksound = q40_mksound; +#endif #ifdef CONFIG_MAGIC_SYSRQ mach_sysrq_key = 0x54; @@ -247,7 +215,9 @@ mach_heartbeat = q40_heartbeat; #endif mach_halt = q40_halt; +#ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; +#endif /* disable a few things that SMSQ might have left enabled */ q40_disable_irqs(); diff -Nru a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c --- a/arch/m68k/sun3/config.c Wed Jul 24 14:03:38 2002 +++ b/arch/m68k/sun3/config.c Wed Jul 24 14:03:38 2002 @@ -151,7 +151,9 @@ mach_default_handler = &sun3_default_handler; mach_request_irq = sun3_request_irq; mach_free_irq = sun3_free_irq; +#ifdef CONFIG_VT // mach_keyb_init = sun3_keyb_init; +#endif enable_irq = sun3_enable_irq; disable_irq = sun3_disable_irq; mach_process_int = sun3_process_int; @@ -162,7 +164,7 @@ mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; mach_get_hardware_list = sun3_get_hardware_list; -#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_FB) +#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif @@ -175,8 +177,9 @@ sun3_bootmem_alloc(memory_start, memory_end); +#ifdef CONFIG_SUN3X_ZS sun_serial_setup(); - +#endif } void __init sun3_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) diff -Nru a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c --- a/arch/m68k/sun3x/config.c Wed Jul 24 14:03:35 2002 +++ b/arch/m68k/sun3x/config.c Wed Jul 24 14:03:35 2002 @@ -61,9 +61,11 @@ mach_get_irq_list = show_sun3_interrupts; mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */ +#ifdef CONFIG_VT mach_keyb_init = sun3x_keyb_init; mach_kbdrate = sun3x_kbdrate; mach_kbd_leds = sun3x_kbd_leds; +#endif mach_default_handler = &sun3_default_handler; mach_sched_init = sun3x_sched_init; diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c --- a/arch/mips/baget/irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/baget/irq.c Wed Jul 24 14:03:38 2002 @@ -186,7 +186,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = *(irq + irq_action); do_random = 0; do { @@ -196,7 +196,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } else { printk("do_IRQ: Unregistered IRQ (0x%X) occurred\n", irq); } diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c --- a/arch/mips/dec/irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/dec/irq.c Wed Jul 24 14:03:38 2002 @@ -136,7 +136,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = *(irq + irq_action); do_random = 0; do { @@ -146,7 +146,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); unmask_irq(irq); } irq_exit(cpu, irq); 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 Jul 24 14:03:35 2002 +++ b/arch/mips/gt64120/momenco_ocelot/irq.c Wed Jul 24 14:03:35 2002 @@ -147,7 +147,7 @@ * int-handler is not on bootstrap */ clear_cp0_status(ST0_IM | ST0_BEV); - __cli(); + local_irq_disable(); /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); 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 Jul 24 14:03:38 2002 +++ b/arch/mips/ite-boards/generic/irq.c Wed Jul 24 14:03:38 2002 @@ -271,12 +271,12 @@ //mask_irq(1<handler %x\n", action->handler); disable_it8172_irq(irq); - //if (!(action->flags & SA_INTERRUPT)) __sti(); /* reenable ints */ + //if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); /* reenable ints */ do { action->handler(irq, action->dev_id, regs); action = action->next; } while ( action ); - //__cli(); /* disable ints */ + //local_irq_disable(); /* disable ints */ if (irq_desc[irq].handler) { } 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 Jul 24 14:03:37 2002 +++ b/arch/mips/ite-boards/generic/time.c Wed Jul 24 14:03:37 2002 @@ -168,7 +168,7 @@ unsigned long count; unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); /* Start counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); @@ -184,7 +184,7 @@ count = read_32bit_cp0_register(CP0_COUNT); /* restore interrupts */ - __restore_flags(flags); + local_irq_restore(flags); return (count / HZ); } diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips/kernel/irq.c Wed Jul 24 14:03:36 2002 @@ -114,7 +114,7 @@ status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -123,7 +123,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); irq_exit(cpu, irq); diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c --- a/arch/mips/kernel/old-irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/kernel/old-irq.c Wed Jul 24 14:03:38 2002 @@ -183,7 +183,7 @@ goto out; if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = *(irq + irq_action); do_random = 0; do { @@ -193,7 +193,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); unmask_irq (irq); out: @@ -219,7 +219,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = *(irq + irq_action); do_random = 0; do { @@ -229,7 +229,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } irq_exit(cpu, irq); diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c --- a/arch/mips/kernel/ptrace.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/kernel/ptrace.c Wed Jul 24 14:03:38 2002 @@ -174,10 +174,10 @@ case FPC_EIR: { /* implementation / version register */ unsigned int flags; - __save_flags(flags); + local_save_flags(flags); enable_cp1(); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - __restore_flags(flags); + local_irq_restore(flags); break; } default: diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c --- a/arch/mips/kernel/smp.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips/kernel/smp.c Wed Jul 24 14:03:36 2002 @@ -281,9 +281,9 @@ printk("Count spun out. Huh?\n"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); if (irqs_running()) continue; if (spin_is_locked(&global_irq_lock)) @@ -335,10 +335,10 @@ { unsigned int flags; - __save_flags(flags); + local_save_flags(flags); if (flags & ST0_IE) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -350,7 +350,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -367,7 +367,7 @@ unsigned long flags; int cpu = smp_processor_id(); - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags & ST0_IE); /* default to local */ retval = 2 + local_enabled; @@ -393,10 +393,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx\n", flags); diff -Nru a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c --- a/arch/mips/lib/dump_tlb.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/lib/dump_tlb.c Wed Jul 24 14:03:38 2002 @@ -102,7 +102,7 @@ unsigned int flags, oldpid; int index; - __save_and_cli(flags); + local_irq_save(flags); oldpid = get_entryhi() & 0xff; BARRIER; set_entryhi((addr & PAGE_MASK) | oldpid); @@ -111,7 +111,7 @@ BARRIER; index = get_index(); set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); if (index < 0) { printk("No entry for address 0x%08lx in TLB\n", addr); diff -Nru a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c --- a/arch/mips/lib/r3k_dump_tlb.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips/lib/r3k_dump_tlb.c Wed Jul 24 14:03:36 2002 @@ -83,13 +83,13 @@ unsigned int flags, oldpid; int index; - __save_and_cli(flags); + local_irq_save(flags); oldpid = get_entryhi() & 0xff; set_entryhi((addr & PAGE_MASK) | oldpid); tlb_probe(); index = get_index(); set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); if (index < 0) { printk("No entry for address 0x%08lx in TLB\n", addr); 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 Jul 24 14:03:38 2002 +++ b/arch/mips/mips-boards/generic/time.c Wed Jul 24 14:03:38 2002 @@ -189,7 +189,7 @@ unsigned long count; unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); /* Start counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); @@ -205,7 +205,7 @@ count = read_32bit_cp0_register(CP0_COUNT); /* restore interrupts */ - __restore_flags(flags); + local_irq_restore(flags); return (count / HZ); } diff -Nru a/arch/mips/mm/mips32.c b/arch/mips/mm/mips32.c --- a/arch/mips/mm/mips32.c Wed Jul 24 14:03:39 2002 +++ b/arch/mips/mm/mips32.c Wed Jul 24 14:03:39 2002 @@ -161,18 +161,18 @@ { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache(); blast_icache(); blast_scache(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void mips32_flush_cache_all_pc(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache(); blast_icache(); - __restore_flags(flags); + local_irq_restore(flags); } static void @@ -198,7 +198,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -208,7 +208,7 @@ blast_scache_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -225,9 +225,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); blast_dcache(); blast_icache(); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -279,7 +279,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -309,7 +309,7 @@ } else blast_scache_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void mips32_flush_cache_page_pc(struct vm_area_struct *vma, @@ -331,7 +331,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -360,7 +360,7 @@ blast_dcache_page_indexed(page); } out: - __restore_flags(flags); + local_irq_restore(flags); } /* If the addresses passed to these routines are valid, they are @@ -420,7 +420,7 @@ if (size >= dcache_size) { flush_cache_all(); } else { - __save_and_cli(flags); + local_irq_save(flags); a = addr & ~(dc_lsize - 1); end = (addr + size) & ~(dc_lsize - 1); while (1) { @@ -428,7 +428,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_wback_inv(addr, size); } @@ -461,7 +461,7 @@ if (size >= dcache_size) { flush_cache_all(); } else { - __save_and_cli(flags); + local_irq_save(flags); a = addr & ~(dc_lsize - 1); end = (addr + size) & ~(dc_lsize - 1); while (1) { @@ -469,7 +469,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_inv(addr, size); @@ -524,7 +524,7 @@ printk("[tlball]"); #endif - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); @@ -546,7 +546,7 @@ } BARRIER; set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } void flush_tlb_mm(struct mm_struct *mm) @@ -557,11 +557,11 @@ #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - __save_and_cli(flags); + local_irq_save(flags); get_new_mmu_context(mm, asid_cache); if (mm == current->active_mm) set_entryhi(mm->context & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -576,7 +576,7 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= mips_cpu.tlbsize/2) { @@ -611,7 +611,7 @@ if (mm == current->active_mm) set_entryhi(mm->context & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -626,7 +626,7 @@ #endif newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -645,7 +645,7 @@ finish: BARRIER; set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -693,7 +693,7 @@ } #endif - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -716,7 +716,7 @@ BARRIER; set_entryhi(pid); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } void show_regs(struct pt_regs * regs) @@ -752,7 +752,7 @@ unsigned long old_pagemask; unsigned long old_ctx; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); @@ -772,7 +772,7 @@ BARRIER; set_pagemask (old_pagemask); flush_tlb_all(); - __restore_flags(flags); + local_irq_restore(flags); } /* Detect and size the various caches. */ @@ -895,7 +895,7 @@ /* This is such a bitch, you'd think they would make it * easy to do this. Away you daemons of stupidity! */ - __save_and_cli(flags); + local_irq_save(flags); /* Fill each size-multiple cache line with a valid tag. */ pow2 = (64 * 1024); @@ -939,7 +939,7 @@ break; pow2 <<= 1; } - __restore_flags(flags); + local_irq_restore(flags); addr -= begin; printk("Secondary cache sized at %dK linesize %d bytes.\n", (int) (addr >> 10), sc_lsize); diff -Nru a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c --- a/arch/mips/mm/r4xx0.c Wed Jul 24 14:03:37 2002 +++ b/arch/mips/mm/r4xx0.c Wed Jul 24 14:03:37 2002 @@ -209,7 +209,7 @@ { unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned int *)KSEG1; __asm__ __volatile__( ".set\tnoreorder\n\t" @@ -236,7 +236,7 @@ "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) :"$1","memory"); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -568,7 +568,7 @@ unsigned long reg1, reg2, reg3, reg4; unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -627,7 +627,7 @@ :"0" (to), "1" (from), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -911,81 +911,81 @@ { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache16(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s32d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache32(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s64d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache64(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s128d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache128(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s32d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache32(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s64d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache64(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s128d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache128(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); - __restore_flags(flags); + local_irq_restore(flags); } static void @@ -1011,7 +1011,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1021,7 +1021,7 @@ blast_scache16_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1049,7 +1049,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1059,7 +1059,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1086,7 +1086,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1096,7 +1096,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1123,7 +1123,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1133,7 +1133,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1160,7 +1160,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1170,7 +1170,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1197,7 +1197,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1207,7 +1207,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1234,7 +1234,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1244,7 +1244,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1261,9 +1261,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1279,9 +1279,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1399,7 +1399,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1429,7 +1429,7 @@ } else blast_scache16_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, @@ -1451,7 +1451,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1480,7 +1480,7 @@ } else blast_scache32_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, @@ -1502,7 +1502,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1531,7 +1531,7 @@ } else blast_scache64_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, @@ -1553,7 +1553,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1583,7 +1583,7 @@ } else blast_scache128_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, @@ -1605,7 +1605,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1635,7 +1635,7 @@ } else blast_scache32_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, @@ -1657,7 +1657,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1687,7 +1687,7 @@ } else blast_scache64_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, @@ -1709,7 +1709,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1738,7 +1738,7 @@ } else blast_scache128_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, @@ -1760,7 +1760,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1789,7 +1789,7 @@ blast_dcache16_page_indexed(page); } out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, @@ -1811,7 +1811,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1841,7 +1841,7 @@ blast_dcache32_page_indexed(page); } out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, @@ -1863,7 +1863,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1893,7 +1893,7 @@ blast_dcache32_page_indexed(page ^ dcache_waybit); } out: - __restore_flags(flags); + local_irq_restore(flags); } /* If the addresses passed to these routines are valid, they are @@ -1939,9 +1939,9 @@ { unsigned long flags; - __save_and_cli(flags); /* For R4600 v1.7 bug. */ + local_irq_save(flags); /* For R4600 v1.7 bug. */ blast_dcache32_page((unsigned long)page_address(page)); - __restore_flags(flags); + local_irq_restore(flags); } static void @@ -1993,7 +1993,7 @@ flush_cache_all(); } else { /* Workaround for R4600 bug. See comment above. */ - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned long *)KSEG1; a = addr & ~(dc_lsize - 1); @@ -2003,7 +2003,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_wback_inv(addr, size); } @@ -2037,7 +2037,7 @@ flush_cache_all(); } else { /* Workaround for R4600 bug. See comment above. */ - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned long *)KSEG1; a = addr & ~(dc_lsize - 1); @@ -2047,7 +2047,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_inv(addr, size); @@ -2094,7 +2094,7 @@ { unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); /* Clear internal cache refill buffer */ *(volatile unsigned int *)KSEG1; @@ -2102,7 +2102,7 @@ protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); - __restore_flags(flags); + local_irq_restore(flags); } #undef DEBUG_TLB @@ -2118,7 +2118,7 @@ printk("[tlball]"); #endif - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); @@ -2138,7 +2138,7 @@ } BARRIER; set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } void flush_tlb_mm(struct mm_struct *mm) @@ -2149,11 +2149,11 @@ #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - __save_and_cli(flags); + local_irq_save(flags); get_new_mmu_context(mm, asid_cache); if (mm == current->active_mm) set_entryhi(mm->context & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -2170,7 +2170,7 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= mips_cpu.tlbsize/2) { @@ -2204,7 +2204,7 @@ if (mm == current->active_mm) set_entryhi(mm->context & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -2219,7 +2219,7 @@ #endif newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -2237,7 +2237,7 @@ finish: BARRIER; set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -2286,7 +2286,7 @@ } #endif - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -2309,7 +2309,7 @@ BARRIER; set_entryhi(pid); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } #if 0 @@ -2322,7 +2322,7 @@ pte_t *ptep; int idx; - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (get_entryhi() & 0xff)); pgdp = pgd_offset(vma->vm_mm, address); @@ -2338,7 +2338,7 @@ else tlb_write_indexed(); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } #endif @@ -2375,7 +2375,7 @@ unsigned long old_pagemask; unsigned long old_ctx; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); @@ -2395,7 +2395,7 @@ BARRIER; set_pagemask (old_pagemask); flush_tlb_all(); - __restore_flags(flags); + local_irq_restore(flags); } /* Detect and size the various r4k caches. */ @@ -2469,7 +2469,7 @@ /* This is such a bitch, you'd think they would make it * easy to do this. Away you daemons of stupidity! */ - __save_and_cli(flags); + local_irq_save(flags); /* Fill each size-multiple cache line with a valid tag. */ pow2 = (64 * 1024); @@ -2513,7 +2513,7 @@ break; pow2 <<= 1; } - __restore_flags(flags); + local_irq_restore(flags); addr -= begin; printk("Secondary cache sized at %dK linesize %d bytes.\n", (int) (addr >> 10), sc_lsize); diff -Nru a/arch/mips/mm/r5432.c b/arch/mips/mm/r5432.c --- a/arch/mips/mm/r5432.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips/mm/r5432.c Wed Jul 24 14:03:38 2002 @@ -554,7 +554,7 @@ printk("[tlball]"); #endif - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); @@ -574,7 +574,7 @@ } BARRIER; set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } void flush_tlb_mm(struct mm_struct *mm) @@ -585,11 +585,11 @@ #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - __save_and_cli(flags); + local_irq_save(flags); get_new_mmu_context(mm, asid_cache); if (mm == current->active_mm) set_entryhi(mm->context & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -604,7 +604,7 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= NTLB_ENTRIES_HALF) { @@ -638,7 +638,7 @@ if (mm == current->active_mm) set_entryhi(mm->context & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -653,7 +653,7 @@ #endif newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -671,7 +671,7 @@ finish: BARRIER; set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -720,7 +720,7 @@ } #endif - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -743,7 +743,7 @@ BARRIER; set_entryhi(pid); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } void show_regs(struct pt_regs * regs) @@ -779,7 +779,7 @@ unsigned long old_pagemask; unsigned long old_ctx; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); @@ -799,7 +799,7 @@ BARRIER; set_pagemask (old_pagemask); flush_tlb_all(); - __restore_flags(flags); + local_irq_restore(flags); } /* Detect and size the various r4k caches. */ diff -Nru a/arch/mips/mm/rm7k.c b/arch/mips/mm/rm7k.c --- a/arch/mips/mm/rm7k.c Wed Jul 24 14:03:35 2002 +++ b/arch/mips/mm/rm7k.c Wed Jul 24 14:03:35 2002 @@ -310,7 +310,7 @@ unsigned long old_ctx; int entry; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = get_entryhi() & 0xff; set_entryhi(KSEG0); @@ -330,7 +330,7 @@ } BARRIER; set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } void flush_tlb_mm(struct mm_struct *mm) @@ -338,11 +338,11 @@ if(mm->context != 0) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); get_new_mmu_context(mm, asid_cache); if (mm == current->mm) set_entryhi(mm->context & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -353,7 +353,7 @@ unsigned long flags; int size; - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if (size <= (ntlb_entries() / 2)) { @@ -387,7 +387,7 @@ if(mm == current->mm) set_entryhi(mm->context & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -399,7 +399,7 @@ newpid = (vma->vm_mm->context & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -417,7 +417,7 @@ finish: BARRIER; set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -460,7 +460,7 @@ pid = get_entryhi() & 0xff; - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -483,7 +483,7 @@ BARRIER; set_entryhi(pid); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } void show_regs(struct pt_regs * regs) @@ -519,7 +519,7 @@ unsigned long old_pagemask; unsigned long old_ctx; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); @@ -539,7 +539,7 @@ BARRIER; set_pagemask (old_pagemask); flush_tlb_all(); - __restore_flags(flags); + local_irq_restore(flags); } /* Used for loading TLB entries before trap_init() has started, when we @@ -557,7 +557,7 @@ unsigned long old_pagemask; unsigned long old_ctx; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); old_pagemask = get_pagemask(); @@ -582,7 +582,7 @@ BARRIER; set_pagemask (old_pagemask); out: - __restore_flags(flags); + local_irq_restore(flags); return ret; } diff -Nru a/arch/mips/mm/sb1.c b/arch/mips/mm/sb1.c --- a/arch/mips/mm/sb1.c Wed Jul 24 14:03:35 2002 +++ b/arch/mips/mm/sb1.c Wed Jul 24 14:03:35 2002 @@ -67,7 +67,7 @@ unsigned long old_ctx; int entry; - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entrylo0(0); @@ -78,7 +78,7 @@ tlb_write_indexed(); } set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c --- a/arch/mips/philips/nino/irq.c Wed Jul 24 14:03:35 2002 +++ b/arch/mips/philips/nino/irq.c Wed Jul 24 14:03:35 2002 @@ -177,7 +177,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do_random = 0; do { do_random |= action->flags; @@ -187,7 +187,7 @@ if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); unmask_irq(irq); - __cli(); + local_irq_disable(); } else { IntClear1 = ~0; IntClear3 = ~0; diff -Nru a/arch/mips/sgi/kernel/indy_sc.c b/arch/mips/sgi/kernel/indy_sc.c --- a/arch/mips/sgi/kernel/indy_sc.c Wed Jul 24 14:03:39 2002 +++ b/arch/mips/sgi/kernel/indy_sc.c Wed Jul 24 14:03:39 2002 @@ -75,7 +75,7 @@ first_line = SC_INDEX(addr); last_line = SC_INDEX(addr + size - 1); - __save_and_cli(flags); + local_irq_save(flags); if (first_line <= last_line) { indy_sc_wipe(first_line, last_line); goto out; @@ -84,7 +84,7 @@ indy_sc_wipe(first_line, SC_SIZE - SC_LINE); indy_sc_wipe(0, last_line); out: - __restore_flags(flags); + local_irq_restore(flags); } static void indy_sc_enable(void) diff -Nru a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c --- a/arch/mips64/kernel/ptrace.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips64/kernel/ptrace.c Wed Jul 24 14:03:36 2002 @@ -158,10 +158,10 @@ break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; - __save_flags(flags); + local_save_flags(flags); set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - __restore_flags(flags); + local_irq_restore(flags); break; } default: @@ -418,10 +418,10 @@ break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; - __save_flags(flags); + local_save_flags(flags); set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - __restore_flags(flags); + local_irq_restore(flags); break; } default: diff -Nru a/arch/mips64/lib/dump_tlb.c b/arch/mips64/lib/dump_tlb.c --- a/arch/mips64/lib/dump_tlb.c Wed Jul 24 14:03:39 2002 +++ b/arch/mips64/lib/dump_tlb.c Wed Jul 24 14:03:39 2002 @@ -101,7 +101,7 @@ unsigned int flags, oldpid; int index; - __save_and_cli(flags); + local_irq_save(flags); oldpid = get_entryhi() & 0xff; BARRIER; set_entryhi((addr & PAGE_MASK) | oldpid); @@ -110,7 +110,7 @@ BARRIER; index = get_index(); set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); if (index < 0) { printk("No entry for address 0x%08lx in TLB\n", addr); diff -Nru a/arch/mips64/mips-boards/generic/time.c b/arch/mips64/mips-boards/generic/time.c --- a/arch/mips64/mips-boards/generic/time.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips64/mips-boards/generic/time.c Wed Jul 24 14:03:36 2002 @@ -188,7 +188,7 @@ unsigned long count; unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); /* Start counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); @@ -204,7 +204,7 @@ count = read_32bit_cp0_register(CP0_COUNT); /* restore interrupts */ - __restore_flags(flags); + local_irq_restore(flags); return (count / HZ); } diff -Nru a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c --- a/arch/mips64/mm/andes.c Wed Jul 24 14:03:35 2002 +++ b/arch/mips64/mm/andes.c Wed Jul 24 14:03:35 2002 @@ -143,7 +143,7 @@ printk("[tlball]"); #endif - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = get_entryhi() & 0xff; set_entryhi(CKSEG0); @@ -159,7 +159,7 @@ entry++; } set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } static void andes_flush_tlb_mm(struct mm_struct *mm) @@ -170,11 +170,11 @@ #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - __save_and_cli(flags); + local_irq_save(flags); get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -192,7 +192,7 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= NTLB_ENTRIES_HALF) { @@ -223,7 +223,7 @@ set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -239,7 +239,7 @@ #endif newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); tlb_probe(); @@ -253,7 +253,7 @@ finish: set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -275,7 +275,7 @@ if (current->active_mm != vma->vm_mm) return; - __save_and_cli(flags); + local_irq_save(flags); pid = get_entryhi() & 0xff; if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || @@ -301,7 +301,7 @@ tlb_write_indexed(); } set_entryhi(pid); - __restore_flags(flags); + local_irq_restore(flags); } static void andes_show_regs(struct pt_regs *regs) diff -Nru a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c --- a/arch/mips64/mm/r4xx0.c Wed Jul 24 14:03:35 2002 +++ b/arch/mips64/mm/r4xx0.c Wed Jul 24 14:03:35 2002 @@ -194,7 +194,7 @@ { unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned int *)KSEG1; __asm__ __volatile__( ".set\tnoreorder\n\t" @@ -217,7 +217,7 @@ :"=r" (page) :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) :"$1", "memory"); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -473,7 +473,7 @@ unsigned long dummy1, dummy2, reg1, reg2; unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -512,7 +512,7 @@ :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) :"0" (to), "1" (from), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D)); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -699,81 +699,81 @@ { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache16(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s32d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache32(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s64d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache64(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s128d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); blast_scache128(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s32d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache32(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s64d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache64(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_s128d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); blast_scache128(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_d16i16(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); - __restore_flags(flags); + local_irq_restore(flags); } static inline void r4k_flush_cache_all_d32i32(void) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_range_s16d16i16(struct vm_area_struct *vma, @@ -799,7 +799,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -809,7 +809,7 @@ blast_scache16_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -837,7 +837,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -847,7 +847,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -875,7 +875,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -885,7 +885,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -913,7 +913,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -923,7 +923,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -951,7 +951,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -961,7 +961,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -989,7 +989,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -999,7 +999,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1027,7 +1027,7 @@ pmd_t *pmd; pte_t *pte; - __save_and_cli(flags); + local_irq_save(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1037,7 +1037,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - __restore_flags(flags); + local_irq_restore(flags); } } } @@ -1054,9 +1054,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16(); blast_icache16(); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1072,9 +1072,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32(); blast_icache32(); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1192,7 +1192,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1221,7 +1221,7 @@ } else blast_scache16_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, @@ -1243,7 +1243,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1271,7 +1271,7 @@ } else blast_scache32_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, @@ -1293,7 +1293,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1322,7 +1322,7 @@ } else blast_scache64_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, @@ -1344,7 +1344,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1374,7 +1374,7 @@ } else blast_scache128_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, @@ -1396,7 +1396,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1427,7 +1427,7 @@ } else blast_scache32_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, @@ -1449,7 +1449,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1480,7 +1480,7 @@ } else blast_scache64_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, @@ -1502,7 +1502,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1531,7 +1531,7 @@ } else blast_scache128_page(page); out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, @@ -1553,7 +1553,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1581,7 +1581,7 @@ blast_dcache16_page_indexed(page); } out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, @@ -1603,7 +1603,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1633,7 +1633,7 @@ blast_dcache32_page_indexed(page); } out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, @@ -1655,7 +1655,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - __save_and_cli(flags); + local_irq_save(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1685,7 +1685,7 @@ blast_dcache32_page_indexed(page ^ dcache_waybit); } out: - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_page_to_ram_s16(struct page *page) @@ -1712,18 +1712,18 @@ { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache16_page((unsigned long)page_address(page)); - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_page_to_ram_d32(struct page *page) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); blast_dcache32_page((unsigned long)page_address(page)); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -1746,7 +1746,7 @@ flush_cache_l1(); } else { /* Workaround for R4600 bug. See comment above. */ - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned long *)KSEG1; a = addr & ~((unsigned long)dc_lsize - 1); @@ -1756,7 +1756,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_wback_inv(addr, size); } @@ -1788,7 +1788,7 @@ flush_cache_l1(); } else { /* Workaround for R4600 bug. See comment above. */ - __save_and_cli(flags); + local_irq_save(flags); *(volatile unsigned long *)KSEG1; a = addr & ~((unsigned long)dc_lsize - 1); @@ -1798,7 +1798,7 @@ if (a == end) break; a += dc_lsize; } - __restore_flags(flags); + local_irq_restore(flags); } bc_inv(addr, size); @@ -1844,7 +1844,7 @@ { unsigned int flags; - __save_and_cli(flags); + local_irq_save(flags); /* Clear internal cache refill buffer */ *(volatile unsigned int *)KSEG1; @@ -1852,7 +1852,7 @@ protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); - __restore_flags(flags); + local_irq_restore(flags); } #undef DEBUG_TLB @@ -1871,7 +1871,7 @@ printk("[tlball]"); #endif - __save_and_cli(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); @@ -1891,7 +1891,7 @@ } BARRIER; set_entryhi(old_ctx); - __restore_flags(flags); + local_irq_restore(flags); } static void r4k_flush_tlb_mm(struct mm_struct *mm) @@ -1902,11 +1902,11 @@ #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - __save_and_cli(flags); + local_irq_save(flags); get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1923,7 +1923,7 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - __save_and_cli(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= NTLB_ENTRIES_HALF) { @@ -1958,7 +1958,7 @@ set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); } - __restore_flags(flags); + local_irq_restore(flags); } } @@ -1973,7 +1973,7 @@ #endif newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); page &= (PAGE_MASK << 1); - __save_and_cli(flags); + local_irq_save(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -1991,7 +1991,7 @@ finish: BARRIER; set_entryhi(oldpid); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -2018,7 +2018,7 @@ if (current->active_mm != vma->vm_mm) return; - __save_and_cli(flags); + local_irq_save(flags); pid = (get_entryhi() & 0xff); #ifdef DEBUG_TLB @@ -2052,7 +2052,7 @@ BARRIER; set_entryhi(pid); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } #if 0 @@ -2065,7 +2065,7 @@ pte_t *ptep; int idx; - __save_and_cli(flags); + local_irq_save(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (get_entryhi() & 0xff)); pgdp = pgd_offset(vma->vm_mm, address); @@ -2081,7 +2081,7 @@ else tlb_write_indexed(); BARRIER; - __restore_flags(flags); + local_irq_restore(flags); } #endif @@ -2171,7 +2171,7 @@ /* This is such a bitch, you'd think they would make it * easy to do this. Away you daemons of stupidity! */ - __save_and_cli(flags); + local_irq_save(flags); /* Fill each size-multiple cache line with a valid tag. */ pow2 = (64 * 1024); @@ -2207,7 +2207,7 @@ break; pow2 <<= 1; } - __restore_flags(flags); + local_irq_restore(flags); addr -= begin; printk("Secondary cache sized at %dK linesize %d\n", (int) (addr >> 10), sc_lsize); diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c --- a/arch/mips64/sgi-ip22/ip22-int.c Wed Jul 24 14:03:36 2002 +++ b/arch/mips64/sgi-ip22/ip22-int.c Wed Jul 24 14:03:36 2002 @@ -306,7 +306,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); action = *(irq + irq_action); do_random = 0; do { @@ -316,7 +316,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } irq_exit(cpu, irq); diff -Nru a/arch/mips64/sgi-ip22/ip22-sc.c b/arch/mips64/sgi-ip22/ip22-sc.c --- a/arch/mips64/sgi-ip22/ip22-sc.c Wed Jul 24 14:03:39 2002 +++ b/arch/mips64/sgi-ip22/ip22-sc.c Wed Jul 24 14:03:39 2002 @@ -58,7 +58,7 @@ first_line = SC_INDEX(addr); last_line = SC_INDEX(addr + size - 1); - __save_and_cli(flags); + local_irq_save(flags); if (first_line <= last_line) { indy_sc_wipe(first_line, last_line); goto out; @@ -67,7 +67,7 @@ indy_sc_wipe(first_line, SC_SIZE - SC_LINE); indy_sc_wipe(0, last_line); out: - __restore_flags(flags); + local_irq_restore(flags); } static void inline indy_sc_enable(void) diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c --- a/arch/mips64/sgi-ip27/ip27-irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/mips64/sgi-ip27/ip27-irq.c Wed Jul 24 14:03:38 2002 @@ -175,7 +175,7 @@ action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do_random = 0; do { do_random |= action->flags; @@ -184,7 +184,7 @@ } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } irq_exit(thiscpu, irq); @@ -506,9 +506,9 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); if (irqs_running()) continue; if (spin_is_locked(&global_irq_lock)) @@ -555,10 +555,10 @@ { unsigned int flags; - __save_flags(flags); + local_save_flags(flags); if (flags & ST0_IE) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -570,7 +570,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -587,7 +587,7 @@ unsigned long flags; int cpu = smp_processor_id(); - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags & ST0_IE); /* default to local */ retval = 2 + local_enabled; @@ -612,10 +612,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx\n", flags); diff -Nru a/arch/ppc/Config.help b/arch/ppc/Config.help --- a/arch/ppc/Config.help Wed Jul 24 14:03:36 2002 +++ b/arch/ppc/Config.help Wed Jul 24 14:03:36 2002 @@ -241,12 +241,6 @@ and strongly recommended if you are compiling a kernel for an Apple machine. -CONFIG_FB_COMPAT_XPMAC - If you use the Xpmac X server (common with mklinux), you'll need to - say Y here to use X. You should consider changing to XFree86 which - includes a server that supports the frame buffer device directly - (XF68_FBDev). - CONFIG_SCSI If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know diff -Nru a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c --- a/arch/ppc/amiga/config.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/amiga/config.c Wed Jul 24 14:03:37 2002 @@ -952,8 +952,9 @@ AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick"); AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot"); if (AMIGAHW_PRESENT(ZORRO)) - len += sprintf(buffer+len, "\tZorro%s AutoConfig: %d Expansion Device%s\n", - AMIGAHW_PRESENT(ZORRO3) ? " III" : "", + len += sprintf(buffer+len, "\tZorro II%s AutoConfig: %d Expansion " + "Device%s\n", + AMIGAHW_PRESENT(ZORRO3) ? "I" : "", zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); #undef AMIGAHW_ANNOUNCE diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in --- a/arch/ppc/config.in Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/config.in Wed Jul 24 14:03:35 2002 @@ -263,7 +263,6 @@ comment 'General setup' bool 'High memory support' CONFIG_HIGHMEM -dep_bool ' Support for PTEs in high memory' CONFIG_HIGHPTE $CONFIG_HIGHMEM bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS if [ "$CONFIG_ADVANCED_OPTIONS" = "y" ]; then if [ "$CONFIG_HIGHMEM" = "y" ]; then @@ -478,9 +477,6 @@ bool 'VGA text console' CONFIG_VGA_CONSOLE fi source drivers/video/Config.in -if [ "$CONFIG_FB" = "y" -a "$CONFIG_ALL_PPC" = "y" ]; then - bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC -fi endmenu diff -Nru a/arch/ppc/kernel/iSeries_head.S b/arch/ppc/kernel/iSeries_head.S --- a/arch/ppc/kernel/iSeries_head.S Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/kernel/iSeries_head.S Wed Jul 24 14:03:37 2002 @@ -1103,7 +1103,7 @@ /* enable and check for decrementers/lpEvents */ mr r3,r31 - bl __restore_flags + bl local_irq_restore /* Restore r3, r4 and LR */ lwz r3,44(r1) @@ -1292,7 +1292,7 @@ /* enable and check for decrementers/lpEvents */ mr r3,r31 - bl __restore_flags + bl local_irq_restore lwz r3,40(r1) mtlr r3 diff -Nru a/arch/ppc/kernel/iSeries_misc.S b/arch/ppc/kernel/iSeries_misc.S --- a/arch/ppc/kernel/iSeries_misc.S Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/kernel/iSeries_misc.S Wed Jul 24 14:03:35 2002 @@ -61,16 +61,16 @@ mtmsr r5 /* restore MSR_EE */ blr -/* void __save_flags(unsigned long *flags) */ -_GLOBAL(__save_flags_ptr) +/* void local_save_flags(unsigned long *flags) */ +_GLOBAL(local_save_flags_ptr) mfspr r4,SPRG1 /* Get Paca pointer */ lbz r4,PACAPROCENABLED(r4) stw r4,0(r3) blr -_GLOBAL(__save_flags_ptr_end) +_GLOBAL(local_save_flags_ptr_end) -/* void __restore_flags(unsigned long flags) */ -_GLOBAL(__restore_flags) +/* void local_irq_restore(unsigned long flags) */ +_GLOBAL(local_irq_restore) cmpi 0,r3,0 /* Are we enabling? */ beq 0f /* No - then skip interrupt checks */ @@ -104,19 +104,19 @@ mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) blr -_GLOBAL(__restore_flags_end) +_GLOBAL(local_irq_restore_end) -_GLOBAL(__cli) +_GLOBAL(local_irq_disable) mfspr r4,SPRG1 li r3,0 stb r3,PACAPROCENABLED(r4) blr /* Done */ -_GLOBAL(__cli_end) +_GLOBAL(local_irq_disable_end) -_GLOBAL(__sti) +_GLOBAL(local_irq_enable) li r3,1 - b __restore_flags -_GLOBAL(__sti_end) + b local_irq_restore +_GLOBAL(local_irq_enable_end) /* * We were about to enable interrupts but we have to simulate diff -Nru a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c --- a/arch/ppc/kernel/idle.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/kernel/idle.c Wed Jul 24 14:03:35 2002 @@ -120,7 +120,7 @@ * Disable interrupts to prevent a lost wakeup * when going to sleep. This is necessary even with * RTLinux since we are not guaranteed an interrupt - * didn't come in and is waiting for a __sti() before + * didn't come in and is waiting for a local_irq_enable() before * emulating one. This way, we really do hard disable. * * We assume that we're sti-ed when we come in here. We @@ -163,8 +163,8 @@ u64 tb; /* Poll for I/O events */ - __cli(); - __sti(); + local_irq_disable(); + local_irq_enable(); paca = (struct Paca *)mfspr(SPRG1); if ( paca->xLpPaca.xSharedProc ) { @@ -181,8 +181,8 @@ * Disabling/enabling will check for LpEvents, IPIs * and decrementers */ - __cli(); - __sti(); + local_irq_disable(); + local_irq_enable(); ++yield_count; @@ -193,14 +193,14 @@ HvCall_yieldProcessor( HvCall_YieldTimed, tb ); /* Check here for any of the above pending or timeout expired*/ - __cli(); + local_irq_disable(); /* * The decrementer stops during the yield. Just force * a fake decrementer now and the timer_interrupt * code will straighten it all out */ paca->xLpPaca.xDecrInt = 1; - __sti(); + local_irq_enable(); } } #endif /* CONFIG_PPC_ISERIES */ diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/kernel/irq.c Wed Jul 24 14:03:37 2002 @@ -422,7 +422,7 @@ int status = 0; if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -431,7 +431,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } /* @@ -637,15 +637,15 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); /* - * We have to allow irqs to arrive between __sti and __cli + * We have to allow irqs to arrive between local_irq_enable and local_irq_disable * Some cpus apparently won't cause the interrupt * for several instructions. We hope that isync will * catch this --Troy */ __asm__ __volatile__ ("isync"); - __cli(); + local_irq_disable(); if (irqs_running()) continue; if (global_irq_lock) @@ -736,10 +736,10 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if (flags & (1 << 15)) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -751,7 +751,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -767,7 +767,7 @@ int local_enabled; unsigned long flags; - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags >> 15) & 1; /* default to local */ retval = 2 + local_enabled; @@ -817,10 +817,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: { diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/kernel/misc.S Wed Jul 24 14:03:37 2002 @@ -207,8 +207,8 @@ bctr #ifndef CONFIG_PPC_ISERIES /* iSeries version is in iSeries_misc.S */ -/* void __save_flags_ptr(unsigned long *flags) */ -_GLOBAL(__save_flags_ptr) +/* void local_save_flags_ptr(unsigned long *flags) */ +_GLOBAL(local_save_flags_ptr) mfmsr r4 stw r4,0(r3) blr @@ -234,10 +234,10 @@ nop nop nop -_GLOBAL(__save_flags_ptr_end) +_GLOBAL(local_save_flags_ptr_end) -/* void __restore_flags(unsigned long flags) */ -_GLOBAL(__restore_flags) +/* void local_irq_restore(unsigned long flags) */ +_GLOBAL(local_irq_restore) /* * Just set/clear the MSR_EE bit through restore/flags but do not * change anything else. This is needed by the RT system and makes @@ -275,9 +275,9 @@ nop nop nop -_GLOBAL(__restore_flags_end) +_GLOBAL(local_irq_restore_end) -_GLOBAL(__cli) +_GLOBAL(local_irq_disable) mfmsr r0 /* Get current interrupt state */ rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */ rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ @@ -304,9 +304,9 @@ nop nop nop -_GLOBAL(__cli_end) +_GLOBAL(local_irq_disable_end) -_GLOBAL(__sti) +_GLOBAL(local_irq_enable) mfmsr r3 /* Get current state */ ori r3,r3,MSR_EE /* Turn on 'EE' bit */ SYNC /* Some chip revs have problems here... */ @@ -333,7 +333,7 @@ nop nop nop -_GLOBAL(__sti_end) +_GLOBAL(local_irq_enable_end) #endif /* CONFIG_PPC_ISERIES */ /* diff -Nru a/arch/ppc/kernel/ppc4xx_setup.c b/arch/ppc/kernel/ppc4xx_setup.c --- a/arch/ppc/kernel/ppc4xx_setup.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/kernel/ppc4xx_setup.c Wed Jul 24 14:03:35 2002 @@ -177,7 +177,7 @@ ppc4xx_power_off(void) { printk("System Halted\n"); - __cli(); + local_irq_disable(); while (1) ; } @@ -185,7 +185,7 @@ ppc4xx_halt(void) { printk("System Halted\n"); - __cli(); + local_irq_disable(); while (1) ; } diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/kernel/ppc_ksyms.c Wed Jul 24 14:03:39 2002 @@ -298,14 +298,14 @@ EXPORT_SYMBOL(__delay); #ifndef INLINE_IRQS -EXPORT_SYMBOL(__sti); -EXPORT_SYMBOL(__sti_end); -EXPORT_SYMBOL(__cli); -EXPORT_SYMBOL(__cli_end); -EXPORT_SYMBOL(__save_flags_ptr); -EXPORT_SYMBOL(__save_flags_ptr_end); -EXPORT_SYMBOL(__restore_flags); -EXPORT_SYMBOL(__restore_flags_end); +EXPORT_SYMBOL(local_irq_enable); +EXPORT_SYMBOL(local_irq_enable_end); +EXPORT_SYMBOL(local_irq_disable); +EXPORT_SYMBOL(local_irq_disable_end); +EXPORT_SYMBOL(local_save_flags_ptr); +EXPORT_SYMBOL(local_save_flags_ptr_end); +EXPORT_SYMBOL(local_irq_restore); +EXPORT_SYMBOL(local_irq_restore_end); #endif EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc/kernel/process.c Wed Jul 24 14:03:38 2002 @@ -202,8 +202,8 @@ struct thread_struct *new_thread, *old_thread; unsigned long s; - __save_flags(s); - __cli(); + local_save_flags(s); + local_irq_disable(); #if CHECK_STACK check_stack(prev); check_stack(new); @@ -246,7 +246,7 @@ new_thread = &new->thread; old_thread = ¤t->thread; _switch(old_thread, new_thread); - __restore_flags(s); + local_irq_restore(s); } void show_regs(struct pt_regs * regs) diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c --- a/arch/ppc/kernel/smp.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/kernel/smp.c Wed Jul 24 14:03:39 2002 @@ -164,7 +164,7 @@ static void stop_this_cpu(void *dummy) { - __cli(); + local_irq_disable(); while (1) ; } @@ -488,9 +488,9 @@ /* FIXME: This doesn't work with hotplug CPUs --RR */ if (!smp_tb_synchronized && num_online_cpus() == 2) { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); smp_software_tb_sync(0); - __restore_flags(flags); + local_irq_restore(flags); } } @@ -514,7 +514,7 @@ if (!smp_tb_synchronized && num_online_cpus() == 2) { smp_software_tb_sync(cpu); } - __sti(); + local_irq_enable(); } /* intel needs this */ diff -Nru a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c --- a/arch/ppc/platforms/adir_setup.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/platforms/adir_setup.c Wed Jul 24 14:03:37 2002 @@ -133,7 +133,7 @@ static void adir_restart(char *cmd) { - __cli(); + local_irq_disable(); /* SRR0 has system reset vector, SRR1 has default MSR value */ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ __asm__ __volatile__ diff -Nru a/arch/ppc/platforms/ev64260_setup.c b/arch/ppc/platforms/ev64260_setup.c --- a/arch/ppc/platforms/ev64260_setup.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc/platforms/ev64260_setup.c Wed Jul 24 14:03:36 2002 @@ -286,7 +286,7 @@ static void ev64260_reset_board(void) { - __cli(); + local_irq_disable(); /* Set exception prefix high - to the firmware */ _nmask_and_or_msr(0, MSR_IP); @@ -310,7 +310,7 @@ static void ev64260_halt(void) { - __cli(); + local_irq_disable(); while (1); /* NOTREACHED */ } diff -Nru a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c --- a/arch/ppc/platforms/gemini_setup.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc/platforms/gemini_setup.c Wed Jul 24 14:03:38 2002 @@ -305,7 +305,7 @@ void gemini_restart(char *cmd) { - __cli(); + local_irq_disable(); /* make a clean restart, not via the MPIC */ _gemini_reboot(); for(;;); diff -Nru a/arch/ppc/platforms/iSeries_pic.c b/arch/ppc/platforms/iSeries_pic.c --- a/arch/ppc/platforms/iSeries_pic.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc/platforms/iSeries_pic.c Wed Jul 24 14:03:38 2002 @@ -65,10 +65,10 @@ lpq = paca->lpQueuePtr; if ( lpq ) { - __save_flags( flags ); - __cli(); + local_save_flags( flags ); + local_irq_disable(); lpEvent_count += ItLpQueue_process( lpq, regs ); - __restore_flags( flags ); + local_irq_restore( flags ); } hardirq_exit( cpu ); diff -Nru a/arch/ppc/platforms/k2_setup.c b/arch/ppc/platforms/k2_setup.c --- a/arch/ppc/platforms/k2_setup.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc/platforms/k2_setup.c Wed Jul 24 14:03:38 2002 @@ -205,7 +205,7 @@ static void k2_restart(char *cmd) { - __cli(); + local_irq_disable(); /* SRR0 has system reset vector, SRR1 has default MSR value */ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ __asm__ __volatile__ diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c --- a/arch/ppc/platforms/lopec_setup.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/platforms/lopec_setup.c Wed Jul 24 14:03:35 2002 @@ -84,7 +84,7 @@ reg |= 0x80; *((unsigned char *) LOPEC_SYSSTAT1) = reg; - __cli(); + local_irq_disable(); while(1); #undef LOPEC_SYSSTAT1 } @@ -92,7 +92,7 @@ static void lopec_halt(void) { - __cli(); + local_irq_disable(); while(1); } diff -Nru a/arch/ppc/platforms/mcpn765_setup.c b/arch/ppc/platforms/mcpn765_setup.c --- a/arch/ppc/platforms/mcpn765_setup.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc/platforms/mcpn765_setup.c Wed Jul 24 14:03:36 2002 @@ -226,7 +226,7 @@ static void mcpn765_reset_board(void) { - __cli(); + local_irq_disable(); /* Set exception prefix high - to the firmware */ _nmask_and_or_msr(0, MSR_IP); @@ -257,7 +257,7 @@ static void mcpn765_halt(void) { - __cli(); + local_irq_disable(); while (1); /* NOTREACHED */ } diff -Nru a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c --- a/arch/ppc/platforms/menf1_setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/platforms/menf1_setup.c Wed Jul 24 14:03:39 2002 @@ -93,7 +93,7 @@ int picr1; struct pci_dev *pdev; - __cli(); + local_irq_disable(); /* * Firmware doesn't like re-entry using Map B (CHRP), so make sure the @@ -130,7 +130,7 @@ static void menf1_halt(void) { - __cli(); + local_irq_disable(); while (1); } diff -Nru a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c --- a/arch/ppc/platforms/mvme5100_setup.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/platforms/mvme5100_setup.c Wed Jul 24 14:03:37 2002 @@ -199,7 +199,7 @@ static void mvme5100_reset_board(void) { - __cli(); + local_irq_disable(); /* Set exception prefix high - to the firmware */ _nmask_and_or_msr(0, MSR_IP); @@ -223,7 +223,7 @@ static void mvme5100_halt(void) { - __cli(); + local_irq_disable(); while (1); } diff -Nru a/arch/ppc/platforms/pcore_setup.c b/arch/ppc/platforms/pcore_setup.c --- a/arch/ppc/platforms/pcore_setup.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/platforms/pcore_setup.c Wed Jul 24 14:03:35 2002 @@ -138,7 +138,7 @@ static void pcore_restart(char *cmd) { - __cli(); + local_irq_disable(); /* Hard reset */ writeb(0x11, 0xfe000332); while(1); @@ -147,7 +147,7 @@ static void pcore_halt(void) { - __cli(); + local_irq_disable(); /* Turn off user LEDs */ writeb(0x00, 0xfe000300); while (1); diff -Nru a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c --- a/arch/ppc/platforms/powerpmc250.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc/platforms/powerpmc250.c Wed Jul 24 14:03:36 2002 @@ -174,7 +174,7 @@ static void powerpmc250_restart(char *cmd) { - __cli(); + local_irq_disable(); /* Hard reset */ writeb(0x11, 0xfe000332); while(1); @@ -183,7 +183,7 @@ static void powerpmc250_halt(void) { - __cli(); + local_irq_disable(); while (1); } diff -Nru a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c --- a/arch/ppc/platforms/pplus_setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/platforms/pplus_setup.c Wed Jul 24 14:03:39 2002 @@ -155,7 +155,7 @@ { unsigned long i = 10000; - __cli(); + local_irq_disable(); /* set VIA IDE controller into native mode */ pplus_set_VIA_IDE_native(); @@ -176,7 +176,7 @@ pplus_halt(void) { unsigned long flags; - __cli(); + local_irq_disable(); /* set exception prefix high - to the prom */ save_flags( flags ); restore_flags( flags|MSR_IP ); diff -Nru a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c --- a/arch/ppc/platforms/prep_setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/platforms/prep_setup.c Wed Jul 24 14:03:39 2002 @@ -473,7 +473,7 @@ if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) panic("Could not allocate timer IRQ!"); - __sti(); + local_irq_enable(); /* wait for calibrate */ while ( calibrate_steps ) ; @@ -565,7 +565,7 @@ { unsigned long i = 10000; - __cli(); + local_irq_disable(); /* set exception prefix high - to the prom */ _nmask_and_or_msr(0, MSR_IP); @@ -583,7 +583,7 @@ prep_halt(void) { unsigned long flags; - __cli(); + local_irq_disable(); /* set exception prefix high - to the prom */ save_flags( flags ); restore_flags( flags|MSR_IP ); @@ -650,7 +650,7 @@ { if ( _prep_type == _PREP_IBM) { unsigned long flags; - __cli(); + local_irq_disable(); /* set exception prefix high - to the prom */ save_flags( flags ); restore_flags( flags|MSR_IP ); diff -Nru a/arch/ppc/platforms/prpmc750_setup.c b/arch/ppc/platforms/prpmc750_setup.c --- a/arch/ppc/platforms/prpmc750_setup.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc/platforms/prpmc750_setup.c Wed Jul 24 14:03:37 2002 @@ -184,7 +184,7 @@ static void prpmc750_restart(char *cmd) { - __cli(); + local_irq_disable(); writeb(PRPMC750_MODRST_MASK, PRPMC750_MODRST_REG); while(1); } @@ -192,7 +192,7 @@ static void prpmc750_halt(void) { - __cli(); + local_irq_disable(); while (1); } diff -Nru a/arch/ppc/platforms/prpmc800_setup.c b/arch/ppc/platforms/prpmc800_setup.c --- a/arch/ppc/platforms/prpmc800_setup.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc/platforms/prpmc800_setup.c Wed Jul 24 14:03:38 2002 @@ -178,7 +178,7 @@ static void prpmc800_restart(char *cmd) { - __cli(); + local_irq_disable(); writeb(HARRIER_RSTOUT_MASK, HARRIER_MISC_CSR_REG); while(1); } @@ -186,7 +186,7 @@ static void prpmc800_halt(void) { - __cli(); + local_irq_disable(); while (1); } diff -Nru a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c --- a/arch/ppc/platforms/sandpoint_setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc/platforms/sandpoint_setup.c Wed Jul 24 14:03:39 2002 @@ -390,7 +390,7 @@ static void sandpoint_restart(char *cmd) { - __cli(); + local_irq_disable(); /* Set exception prefix high - to the firmware */ _nmask_and_or_msr(0, MSR_IP); @@ -404,7 +404,7 @@ static void sandpoint_power_off(void) { - __cli(); + local_irq_disable(); for(;;); /* No way to shut power off with software */ /* NOTREACHED */ } diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c --- a/arch/ppc/platforms/spruce_setup.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc/platforms/spruce_setup.c Wed Jul 24 14:03:36 2002 @@ -158,7 +158,7 @@ static void spruce_restart(char *cmd) { - __cli(); + local_irq_disable(); /* SRR0 has system reset vector, SRR1 has default MSR value */ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ diff -Nru a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c --- a/arch/ppc/platforms/zx4500_setup.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/platforms/zx4500_setup.c Wed Jul 24 14:03:35 2002 @@ -191,7 +191,7 @@ static void zx4500_restart(char *cmd) { - __cli(); + local_irq_disable(); out_8((volatile u_char *)ZX4500_CPLD_RESET, ZX4500_CPLD_RESET_XBUS); for (;;); @@ -203,7 +203,7 @@ static void zx4500_power_off(void) { - __cli(); + local_irq_disable(); for(;;); /* No way to shut power off with software */ /* NOTREACHED */ } diff -Nru a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c --- a/arch/ppc/xmon/xmon.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc/xmon/xmon.c Wed Jul 24 14:03:35 2002 @@ -243,11 +243,11 @@ xmon_irq(int irq, void *d, struct pt_regs *regs) { unsigned long flags; - __save_flags(flags); - __cli(); + local_save_flags(flags); + local_irq_disable(); printf("Keyboard interrupt\n"); xmon(regs); - __restore_flags(flags); + local_irq_restore(flags); } int diff -Nru a/arch/ppc64/Config.help b/arch/ppc64/Config.help --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/Config.help Wed Jul 24 14:03:39 2002 @@ -0,0 +1,299 @@ +CONFIG_SMP + This enables support for systems with more than one CPU. If you have + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. Note that the kernel does not currently + support SMP machines with 603/603e/603ev or PPC750 ("G3") processors + since they have inadequate hardware support for multiprocessor + operation. + + If you say N here, the kernel will run on single and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on single-processor machines. + On a single-processor machine, the kernel will run faster if you say + N here. + + If you don't know what to do here, say N. + +CONFIG_PREEMPT + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + Unfortunately the kernel code has some race conditions if both + CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is + currently disabled if you are building an SMP kernel. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. + +CONFIG_IDE + If you say Y here, your kernel will be able to manage low cost mass + storage units such as ATA/(E)IDE and ATAPI units. The most common + cases are IDE hard drives and ATAPI CD-ROM drives. + + If your system is pure SCSI and doesn't use these interfaces, you + can say N here. + + Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard + for mass storage units such as hard disks. It was designed by + Western Digital and Compaq Computer in 1984. Quite a number of + disks use the IDE interface. + + Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is + ATA-3. It provides support for larger disks (up to 8.4GB by means of + the LBA standard), more disks (4 instead of 2) and for other mass + storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is + ATA-4 and provides faster (and more CPU friendly) transfer modes + than previous PIO (Programmed processor Input/Output) from previous + ATA/IDE standards by means of fast DMA controllers. + + ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and + CD-ROM drives, similar in many respects to the SCSI protocol. + + SMART IDE (Self Monitoring, Analysis and Reporting Technology) was + designed in order to prevent data corruption and disk crash by + detecting pre hardware failure conditions (heat, access time, and + the like...). Disks built since June 1995 may follow this standard. + The kernel itself don't manage this; however there are quite a + number of user programs such as smart that can query the status of + SMART parameters disk. + + If you want to compile this 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 ide.o. + + For further information, please read . + + If unsure, say Y. + +CONFIG_ISA + Find out whether you have ISA slots on your motherboard. ISA is the + name of a bus system, i.e. the way the CPU talks to the other stuff + inside your box. If you have an Apple machine, say N here; if you + have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If + you have an embedded board, consult your board documentation. + +CONFIG_PCI + Find out whether your system includes a PCI bus. PCI is the name of + a bus system, i.e. the way the CPU talks to the other stuff inside + your box. If you say Y here, the kernel will include drivers and + infrastructure code to support PCI bus devices. + +CONFIG_HOTPLUG + 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. + +CONFIG_PCMCIA + Say Y here if you want to attach PCMCIA- or PC-cards to your Linux + computer. These are credit-card size devices such as network cards, + modems or hard drives often used with laptops computers. There are + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. If you want to use CardBus + cards, you need to say Y here and also to "CardBus support" below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file + for location). Please also read the PCMCIA-HOWTO, available from + . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + When compiled this way, there will be modules called pcmcia_core.o + and ds.o. If you want to compile it as a module, say M here and + read . + +CONFIG_KCORE_ELF + If you enabled support for /proc file system then the file + /proc/kcore will contain the kernel core image in ELF format. This + can be used in gdb: + + $ cd /usr/src/linux ; gdb vmlinux /proc/kcore + + This is especially useful if you have compiled the kernel with the + "-g" option to preserve debugging information. It is mainly used + for examining kernel data structures on the live kernel. + +CONFIG_BINFMT_ELF + ELF (Executable and Linkable Format) is a format for libraries and + executables used across different architectures and operating + systems. + +CONFIG_BINFMT_MISC + If you say Y here, it will be possible to plug wrapper-driven binary + formats into the kernel. You will like this especially when you use + programs that need an interpreter to run like Java, Python or + Emacs-Lisp. It's also useful if you often run DOS executables under + the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from + ). Once you have + registered such a binary class with the kernel, you can start one of + those programs simply by typing in its name at a shell prompt; Linux + will automatically feed it to the correct interpreter. + + You can do other nice things, too. Read the file + to learn how to use this + feature, and for information about how + to include Java support. + + You must say Y to "/proc file system support" (CONFIG_PROC_FS) to + use this part of the kernel. + + You may say M here for module support and later load the module when + you have use for it; the module is called binfmt_misc.o. If you + don't know what to answer at this point, say Y. + +CONFIG_VGA_CONSOLE + Saying Y here will allow you to use Linux in text mode through a + display that complies with the generic VGA standard. This can be + useful on PReP systems and IBM RS/6000 or pSeries machines but is of + limited usefulness on Apple machines. + + Say N here if you have an Apple machine. + +CONFIG_IRQ_ALL_CPUS + This option gives the kernel permission to distribute IRQs across + multiple CPUs. Saying N here will route all IRQs to the first + CPU. Generally saying Y is safe, although some problems have been + reported with SMP Power Macintoshes with this option enabled. + +CONFIG_FB + The frame buffer device provides an abstraction for the graphics + hardware. It represents the frame buffer of some video hardware and + allows application software to access the graphics hardware through + a well-defined interface, so the software doesn't need to know + anything about the low-level (hardware register) stuff. + + Frame buffer devices work identically across the different + architectures supported by Linux and make the implementation of + application programs easier and more portable; at this point, an X + server exists which uses the frame buffer device exclusively. + On several non-X86 architectures, the frame buffer device is the + only way to use the graphics hardware. + + The device is accessed through special device nodes, usually located + in the /dev directory, i.e. /dev/fb*. + + 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. + + Saying Y here is recommended if your machine has graphics hardware, + and strongly recommended if you are compiling a kernel for an Apple + machine. + +CONFIG_SCSI + If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or + any other SCSI device under Linux, say Y and make sure that you know + the name of your SCSI host adapter (the card inside your computer + that "speaks" the SCSI protocol, also called SCSI controller), + because you will be asked for it. + + You also need to say Y here if you want support for the parallel + port version of the 100 MB IOMEGA ZIP drive. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called scsi_mod.o. If you want to compile it as + a module, say M here and read and + . However, do not compile this as a + module if your root file system (the one containing the directory /) + is located on a SCSI device. + +CONFIG_NETDEVICES + You can say N here if you don't intend to connect your Linux box to + any other computer at all or if all your connections will be over a + telephone line with a modem either via UUCP (UUCP is a protocol to + forward mail and news between unix hosts over telephone lines; read + the UUCP-HOWTO, available from + ) or dialing up a shell + account or a BBS, even using term (term is a program which gives you + almost full Internet connectivity if you have a regular dial up + shell account on some Internet connected Unix computer. Read + ). + + You'll have to say Y if your computer contains a network card that + you want to use under Linux (make sure you know its name because you + will be asked for it and read the Ethernet-HOWTO (especially if you + plan to use more than one network card under Linux)) or if you want + to use SLIP (Serial Line Internet Protocol is the protocol used to + send Internet traffic over telephone lines or null modem cables) or + CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better + and newer replacement for SLIP) or PLIP (Parallel Line Internet + Protocol is mainly used to create a mini network by connecting the + parallel ports of two local machines) or AX.25/KISS (protocol for + sending Internet traffic over amateur radio links). + + Make sure to read the NET-3-HOWTO. Eventually, you will have to read + Olaf Kirch's excellent and free book "Network Administrator's + Guide", to be found in . If + unsure, say Y. + +CONFIG_SERIAL_CONSOLE + 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). This could be useful if some terminal or printer is connected + to that serial port. + + 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=ttyS1". (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 you don't have a graphics card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + If unsure, say N. + +CONFIG_MOUSE + This is for machines with a mouse which is neither a serial nor a + USB nor a bus mouse. Examples are PS/2 mice (including the track + balls on some laptops) and some digitizer pads. Say Y here if you + have a CHRP machine (such as an IBM RS/6000 or pSeries machine) with + a PS/2-style mouse. + + 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 non-serial mice. If unsure, say Y. + +CONFIG_MAGIC_SYSRQ + 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 + will be able to flush the buffer cache to disk, reboot the system + immediately or dump some status information). This is accomplished + by pressing various keys while holding SysRq (Alt+PrintScreen). It + also works on a serial console (on PC hardware at least), if you + send a BREAK and then within 5 seconds a command keypress. The + keys are documented in . Don't say Y + unless you really know what this hack does. + +CONFIG_PROC_DEVICETREE + This option adds a device-tree directory under /proc which contains + an image of the device tree that the kernel copies from Open + Firmware. If unsure, say Y here. + +CONFIG_CMDLINE + 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 + most cases you will need to specify the root device here. + +CONFIG_XMON + Include in-kernel hooks for the xmon kernel monitor/debugger. + Unless you are intending to debug the kernel, say N here. diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/Makefile Wed Jul 24 14:03:36 2002 @@ -15,11 +15,12 @@ KERNELLOAD =0xc000000000000000 +LDFLAGS := -m elf64ppc LDFLAGS_vmlinux = -T arch/ppc64/vmlinux.lds -Bstatic \ -e $(KERNELLOAD) -Ttext $(KERNELLOAD) CFLAGS := $(CFLAGS) -fsigned-char -msoft-float -pipe \ -Wno-uninitialized -mminimal-toc -mtraceback=full \ - -Wa,-mpower4 -finline-limit-2000 + -Wa,-mpower4 -finline-limit-2000 -mcpu=630 CPP = $(CC) -E $(CFLAGS) @@ -65,6 +66,3 @@ @$(MAKEBOOT) clean archmrproper: - -prepare: - $(MAKEBOOT) dep diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile --- a/arch/ppc64/boot/Makefile Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/boot/Makefile Wed Jul 24 14:03:37 2002 @@ -120,7 +120,3 @@ clean: rm -f piggyback note addnote $(OBJS) zImage zImage.initrd vmlinux.gz no_initrd.o imagesize.c addSystemMap vmlinux.sm addRamDisk vmlinux.initrd vmlinux.sminitrd - -dep: - $(CPP) $(CPPFLAGS) -M *.S *.c > .depend - diff -Nru a/arch/ppc64/config.in b/arch/ppc64/config.in --- a/arch/ppc64/config.in Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/config.in Wed Jul 24 14:03:36 2002 @@ -23,12 +23,18 @@ bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS if [ "$CONFIG_PPC_PSERIES" = "y" ]; then bool ' Hardware multithreading' CONFIG_HMT + bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM + if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then + bool ' NUMA support' CONFIG_NUMA + fi fi fi define_bool CONFIG_PREEMPT n if [ "$CONFIG_PPC_ISERIES" = "y" ]; then define_bool CONFIG_MSCHUNKS y +else + tristate ' Firmware flash interface' CONFIG_RTAS_FLASH fi endmenu diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig --- a/arch/ppc64/defconfig Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/defconfig Wed Jul 24 14:03:37 2002 @@ -37,7 +37,9 @@ CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y # CONFIG_HMT is not set +# CONFIG_DISCONTIGMEM is not set # CONFIG_PREEMPT is not set +# CONFIG_RTAS_FLASH is not set # # General setup @@ -60,6 +62,7 @@ # # CONFIG_PARPORT is not set CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set # # Memory Technology Devices (MTD) @@ -83,6 +86,7 @@ # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_CISS_SCSI_TAPE 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_NBD=y CONFIG_BLK_DEV_RAM=y @@ -188,9 +192,6 @@ # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set @@ -225,7 +226,6 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set @@ -238,6 +238,10 @@ # Fusion MPT device support # # CONFIG_FUSION is not set +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -364,7 +368,7 @@ # CONFIG_WAN is not set # -# "Tulip" family network device support +# Tulip family network device support # # CONFIG_NET_TULIP is not set @@ -397,7 +401,6 @@ # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set # CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -409,6 +412,7 @@ # CONFIG_FB_IMSTT is not set # CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set +# CONFIG_FB_RIVA is not set CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y @@ -422,6 +426,8 @@ # 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_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB8=y @@ -440,20 +446,40 @@ # Input device support # # CONFIG_INPUT is not set + +# +# Userland interfaces +# # CONFIG_INPUT_KEYBDEV is not set # CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX 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 +# CONFIG_INPUT_UINPUT is not set + +# +# Input I/O drivers +# # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_GAMEPORT_NS558 is not set # CONFIG_GAMEPORT_L4 is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_GAMEPORT_PCIGAME is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set # CONFIG_GAMEPORT_FM801 is not set # CONFIG_GAMEPORT_CS461x is not set # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_Q40KBD is not set +# CONFIG_SERIO_PARKBD is not set + +# +# Input Device Drivers +# CONFIG_VIOPATH=y # @@ -478,17 +504,15 @@ # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -509,6 +533,8 @@ # File systems # # CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set CONFIG_REISERFS_FS=y diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/LparData.c Wed Jul 24 14:03:36 2002 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +144,8 @@ struct ItIplParmsReal xItIplParmsReal = {}; +struct ItExtVpdPanel xItExtVpdPanel = {}; + #define maxPhysicalProcessors 32 struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = { @@ -185,7 +187,8 @@ {0}, /* DMA lengths */ {0}, /* DMA tokens */ { /* VPD lengths */ - 0,0,0,0, /* 0 - 3 */ + 0,0,0, /* 0 - 2 */ + sizeof(xItExtVpdPanel), /* 3 Extended VPD */ sizeof(struct paca_struct), /* 4 length of Paca */ 0, /* 5 */ sizeof(struct ItIplParmsReal),/* 6 length of IPL parms */ @@ -202,7 +205,8 @@ 0,0 /* 24 - 25 */ }, { /* VPD addresses */ - 0,0,0,0, /* 0 - 3 */ + 0,0,0, /* 0 - 2 */ + &xItExtVpdPanel, /* 3 Extended VPD */ &paca[0], /* 4 first Paca */ 0, /* 5 */ &xItIplParmsReal, /* 6 IPL parms */ @@ -244,6 +248,7 @@ return mem; } + diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/Makefile Wed Jul 24 14:03:39 2002 @@ -32,6 +32,8 @@ obj-y += rtasd.o nvram.o endif +obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o + obj-$(CONFIG_SMP) += smp.o obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o @@ -43,6 +45,11 @@ # head.o: head.S ppc_defs.h +misc.o: misc.S ppc_defs.h +entry.o: entry.S ppc_defs.h +hvCall.o: hvCall.S ppc_defs.h +pSeries_hvCall.o: pSeries_hvCall.S ppc_defs.h +sys32.o: sys32.S ppc_defs.h ppc_defs.h: mk_defs.c ppc_defs.head \ $(TOPDIR)/include/asm/mmu.h \ diff -Nru a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c --- a/arch/ppc64/kernel/XmPciLpEvent.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/XmPciLpEvent.c Wed Jul 24 14:03:38 2002 @@ -26,10 +26,13 @@ enum XmPciLpEvent_Subtype { XmPciLpEvent_BusCreated = 0, // PHB has been created - XmPciLpEvent_BusFailed = 1, // PHB has failed - XmPciLpEvent_BusRecovered = 12, // PHB has been recovered + XmPciLpEvent_BusError = 1, // PHB has failed + XmPciLpEvent_BusFailed = 2, // Msg to Seconday, Primary failed bus XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered + XmPciLpEvent_BusRecovered = 12, // PHB has been recovered + XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing + XmPciLpEvent_BridgeError = 21, // Bridge Error XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt }; @@ -116,13 +119,16 @@ case XmPciLpEvent_BusCreated: printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber); break; + case XmPciLpEvent_BusError: case XmPciLpEvent_BusFailed: printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber); break; case XmPciLpEvent_BusRecovered: + case XmPciLpEvent_UnQuiesceBus: printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber); break; case XmPciLpEvent_NodeFailed: + case XmPciLpEvent_BridgeError: printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId); break; case XmPciLpEvent_NodeRecovered: diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/align.c Wed Jul 24 14:03:38 2002 @@ -238,7 +238,7 @@ dsisr = regs->dsisr; /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4)) + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) dsisr = make_dsisr( *((unsigned *)regs->nip) ); /* extract the operation and registers from the dsisr */ diff -Nru a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c --- a/arch/ppc64/kernel/binfmt_elf32.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/binfmt_elf32.c Wed Jul 24 14:03:36 2002 @@ -62,6 +62,16 @@ char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; +#include + +#define jiffies_to_timeval jiffies_to_timeval32 +static __inline__ void +jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value) +{ + value->tv_usec = (jiffies % HZ) * (1000000L / HZ); + value->tv_sec = jiffies / HZ; +} + extern void start_thread32(struct pt_regs *, unsigned long, unsigned long); #undef start_thread #define start_thread start_thread32 diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/chrp_setup.c Wed Jul 24 14:03:36 2002 @@ -57,7 +57,6 @@ #include #include #include -#include #include #include @@ -98,16 +97,10 @@ kdev_t boot_dev; unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address. -extern HPTE *Hash, *Hash_end; -extern unsigned long Hash_size, Hash_mask; -extern int probingmem; extern unsigned long loops_per_jiffy; -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif +extern unsigned long ppc_proc_freq; +extern unsigned long ppc_tb_freq; void chrp_get_cpuinfo(struct seq_file *m) @@ -115,6 +108,8 @@ struct device_node *root; const char *model = ""; + seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); + root = find_path_device("/"); if (root) model = get_property(root, "model", NULL); @@ -304,7 +299,7 @@ ppc_md.progress("Linux ppc64\n", 0x0); } -void __chrp +void chrp_progress(char *s, unsigned short hex) { struct device_node *root; @@ -361,9 +356,6 @@ } extern void setup_default_decr(void); - -extern unsigned long ppc_proc_freq; -extern unsigned long ppc_tb_freq; void __init pSeries_calibrate_decr(void) { diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c --- a/arch/ppc64/kernel/eeh.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/eeh.c Wed Jul 24 14:03:38 2002 @@ -59,15 +59,14 @@ return ((IO_UNMAPPED_REGION_ID << 60) | (phb << 48UL) | ((bus & 0xff) << 40UL) | (devfn << 32UL) | (offset & 0xffffffff)); } - - -int eeh_get_state(unsigned long ea) { +int eeh_get_state(unsigned long ea) +{ return 0; } - /* Check for an eeh failure at the given token address. - * The given value has been read and it should be 1's (0xff, 0xffff or 0xffffffff). + * The given value has been read and it should be 1's (0xff, 0xffff or + * 0xffffffff). * * Probe to determine if an error actually occurred. If not return val. * Otherwise panic. @@ -113,7 +112,8 @@ return val; /* good case */ } -void eeh_init(void) { +void eeh_init(void) +{ 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"); @@ -121,7 +121,7 @@ ibm_set_eeh_option = rtas_token("ibm,set-eeh-option"); ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); - if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE && naca->platform == PLATFORM_PSERIES_LPAR) + if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE) eeh_implemented = 1; if (eeh_force_off > eeh_force_on) { @@ -334,6 +334,7 @@ { return eeh_parm(str, 0); } + static int __init eehon_parm(char *str) { return eeh_parm(str, 1); diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Wed Jul 24 14:03:35 2002 +++ b/arch/ppc64/kernel/entry.S Wed Jul 24 14:03:35 2002 @@ -64,7 +64,8 @@ #ifdef SHOW_SYSCALLS_TASK LOADBASE(r31,show_syscalls_task) ld r31,show_syscalls_task@l(r31) - cmp 0,r13,r31 + ld r10,PACACURRENT(r13) + cmp 0,r10,r31 bne 1f #endif LOADADDR(r3,7f) @@ -78,7 +79,7 @@ LOADADDR(r3,77f) ld r4,GPR8(r1) ld r5,GPR9(r1) - mr r6,r13 + ld r6, PACACURRENT(r13) bl .printk ld r0,GPR0(r1) ld r3,GPR3(r1) @@ -129,7 +130,8 @@ 20: std r3,RESULT(r1) /* Save result */ #ifdef SHOW_SYSCALLS #ifdef SHOW_SYSCALLS_TASK - cmp 0,r13,r31 + ld r10, PACACURRENT(13) + cmp 0,r10,r31 bne 91f #endif mr r4,r3 @@ -289,9 +291,8 @@ std r23,_CCR(r1) std r1,KSP(r3) /* Set old stack pointer */ - mfspr r5,SPRG3 /* Get paca */ - addi r13,r4,-THREAD /* Convert THREAD to 'current' */ - std r13,PACACURRENT(r5) /* Set new 'current' */ + addi r6,r4,-THREAD /* Convert THREAD to 'current' */ + std r6,PACACURRENT(r13) /* Set new 'current' */ #ifdef CONFIG_PPC_ISERIES #error fixme @@ -335,6 +336,7 @@ CHECKANYINT(r3,r4) beq+ 4f /* skip do_IRQ if no interrupts */ +#warning FIX ISERIES mfspr r5,SPRG3 li r3,0 stb r3,PACAPROCENABLED(r5) /* ensure we are disabled */ @@ -353,7 +355,7 @@ li r4,0 ori r4,r4,MSR_EE|MSR_RI andc r10,r10,r4 /* clear MSR_EE and MSR_RI */ - mtmsrd r10 /* Update machine state */ + mtmsrd r10,1 /* Update machine state */ #ifdef CONFIG_PPC_ISERIES #error fix iSeries soft disable @@ -370,9 +372,15 @@ bne do_work addi r0,r1,INT_FRAME_SIZE /* size of frame */ - std r0,THREAD+KSP(r13) /* save kernel stack pointer */ - mfspr r4,SPRG3 /* current task's PACA */ - std r1,PACAKSAVE(r4) /* save exception stack pointer */ + ld r4,PACACURRENT(r13) + std r0,THREAD+KSP(r4) /* save kernel stack pointer */ + std r1,PACAKSAVE(r13) /* save exception stack pointer */ + + /* + * r13 is our per cpu area, only restore it if we are returning to + * userspace + */ + REST_GPR(13,r1) restore: ld r3,_CTR(r1) @@ -389,29 +397,37 @@ stdcx. r0,0,r1 /* to clear the reservation */ #ifdef DO_SOFT_DISABLE + /* XXX do this in do_work, r13 isnt valid here */ ld r0,SOFTE(r1) stb r0,PACAPROCENABLED(r13) #endif ld r0,_MSR(r1) mtspr SRR1,r0 + ld r2,_CCR(r1) mtcrf 0xFF,r2 ld r2,_NIP(r1) mtspr SRR0,r2 - REST_GPR(13,r1) + ld r0,GPR0(r1) ld r2,GPR2(r1) ld r3,GPR3(r1) ld r4,GPR4(r1) ld r1,GPR1(r1) + /* + * What if we took an exception and stole this segment, we may + * fault on the above addresses and globber SRR0/1. Should check RI + * bit and repeat - Anton + */ rfid +/* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: /* Enable interrupts */ ori r10,r10,MSR_EE|MSR_RI - mtmsrd r10 + mtmsrd r10,1 andi. r0,r3,_TIF_NEED_RESCHED beq 1f @@ -419,15 +435,12 @@ b recheck 1: andi. r0,r3,_TIF_SIGPENDING - beq 2f + beq recheck li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD bl .do_signal b recheck -2: /* nobody uses the TIF_NOTIFY_RESUME bit yet */ - b recheck - /* * On CHRP, the Run-Time Abstraction Services (RTAS) have to be * called with the MMU off. @@ -446,7 +459,7 @@ * RTAS might touch to the stack. (r0, r3-r13 are caller saved) */ SAVE_GPR(2, r1) /* Save the TOC */ - SAVE_GPR(13, r1) /* Save current */ + SAVE_GPR(13, r1) /* Save paca */ SAVE_8GPRS(14, r1) /* Save the non-volatiles */ SAVE_10GPRS(22, r1) /* ditto */ @@ -465,14 +478,13 @@ mfsrr1 r10 std r10,_SRR1(r1) - /* Unfortunatly, the stack pointer and the MSR are also clobbered, - * so they are saved in the PACA (SPRG3) which allows us to restore + /* Unfortunately, the stack pointer and the MSR are also clobbered, + * so they are saved in the PACA which allows us to restore * our original state after RTAS returns. */ - mfspr r4,SPRG3 /* Get PACA */ - std r1,PACAR1(r4) + std r1,PACAR1(r13) mfmsr r6 - std r6,PACASAVEDMSR(r4) + std r6,PACASAVEDMSR(r13) /* Setup our real return addr */ SET_REG_TO_LABEL(r4,.rtas_return_loc) @@ -516,13 +528,11 @@ _STATIC(rtas_restore_regs) /* relocation is on at this point */ REST_GPR(2, r1) /* Restore the TOC */ - REST_GPR(13, r1) /* Restore current */ + REST_GPR(13, r1) /* Restore paca */ REST_8GPRS(14, r1) /* Restore the non-volatiles */ REST_10GPRS(22, r1) /* ditto */ - /* put back current in r13 */ - mfspr r4,SPRG3 - ld r13,PACACURRENT(r4) + mfspr r13,SPRG3 ld r4,_CCR(r1) mtcr r4 @@ -555,7 +565,7 @@ * 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 current */ + SAVE_GPR(13, r1) /* Save paca */ SAVE_8GPRS(14, r1) /* Save the non-volatiles */ SAVE_10GPRS(22, r1) /* ditto */ @@ -600,7 +610,7 @@ isync REST_8GPRS(2, r1) /* Restore the TOC & param(s) */ - REST_GPR(13, r1) /* Restore current */ + REST_GPR(13, r1) /* Restore paca */ REST_8GPRS(14, r1) /* Restore the non-volatiles */ REST_10GPRS(22, r1) /* ditto */ blrl /* Entering PROM here... */ @@ -611,7 +621,7 @@ isync REST_GPR(2, r1) /* Restore the TOC */ - REST_GPR(13, r1) /* Restore current */ + REST_GPR(13, r1) /* Restore paca */ REST_8GPRS(14, r1) /* Restore the non-volatiles */ REST_10GPRS(22, r1) /* ditto */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/head.S Wed Jul 24 14:03:38 2002 @@ -37,6 +37,12 @@ #endif /* + * hcall interface to pSeries LPAR + */ +#define HSC .long 0x44000022 +#define H_SET_ASR 0x30 + +/* * We layout physical memory as follows: * 0x0000 - 0x00ff : Secondary processor spin code * 0x0100 - 0x2fff : pSeries Interrupt prologs @@ -152,7 +158,7 @@ */ /* - * This is the start of the interrupt handlers for Pseries + * This is the start of the interrupt handlers for pSeries * This code runs with relocation off. */ #define EX_SRR0 0 @@ -193,7 +199,7 @@ rfid /* - * This is the start of the interrupt handlers for i_series + * This is the start of the interrupt handlers for iSeries * This code runs with relocation on. */ #define EXCEPTION_PROLOG_ISERIES(n) \ @@ -269,7 +275,7 @@ SAVE_8GPRS(2, r1); /* save r2 - r13 in stackframe */ \ SAVE_4GPRS(10, r1); \ ld r2,PACATOC(r20); \ - ld r13,PACACURRENT(r20) + mr r13,r20 /* * Note: code which follows this uses cr0.eq (set if from kernel), @@ -427,8 +433,8 @@ .globl SystemReset_Iseries SystemReset_Iseries: - mfspr 25,SPRG3 /* Get paca address */ - lhz r24,PACAPACAINDEX(r25) /* Get processor # */ + mfspr r13,SPRG3 /* Get paca address */ + lhz r24,PACAPACAINDEX(r13) /* Get processor # */ cmpi 0,r24,0 /* Are we processor 0? */ beq .__start_initialization_iSeries /* Start up the first processor */ mfspr r4,CTRLF @@ -439,7 +445,7 @@ 1: HMT_LOW #ifdef CONFIG_SMP - lbz r23,PACAPROCSTART(r25) /* Test if this processor + lbz r23,PACAPROCSTART(r13) /* Test if this processor * should start */ sync LOADADDR(r3,current_set) @@ -469,7 +475,7 @@ #endif /* CONFIG_SMP */ li r0,-1 /* r0=-1 indicates a Hypervisor call */ sc /* Invoke the hypervisor via a system call */ - mfspr r25,SPRG3 /* Put r25 back ???? */ + mfspr r13,SPRG3 /* Put r13 back ???? */ b 1b /* If SMP not configured, secondaries * loop forever */ @@ -575,7 +581,8 @@ bl .do_stab_SI b 1f -2: bl .do_hash_page_DSI /* Try to handle as hpte fault */ +2: li r5,0x300 + bl .do_hash_page_DSI /* Try to handle as hpte fault */ 1: ld r4,_DAR(r1) ld r5,_DSISR(r1) @@ -627,9 +634,8 @@ bl .do_stab_SI b 1f -2: andis. r0,r23,0x4000 /* no pte found? */ - beq 1f /* if so, try to put a PTE */ - mr r3,r22 /* into the hash table */ +2: mr r3,r22 + li r5,0x400 bl .do_hash_page_ISI /* Try to handle as hpte fault */ 1: mr r4,r22 @@ -660,7 +666,7 @@ #else rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ #endif - li r6,0x380 + li r6,0x480 bl .save_remaining_regs bl .do_page_fault b .ret_from_except @@ -682,33 +688,41 @@ /* */ /* The call to do_irq will preserve the value of r14 - r31 */ /* */ - mfspr r20,SPRG3 /* get paca */ - lbz r21,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ +/* + * XXX turn off interrupt stacks until the thread_info stuff is fixed. + * Otherwise we end up setting need_resched etc bits in the interrupt + * stack and they never get seen when we return to the process stack - Anton + */ +#if 0 + lbz r21,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ cmpi 0,r21,1 /* */ addi r21,r21,1 /* incr hardware interrupt cnt*/ - stb r21,PACAHRDWINTCOUNT(r20) /* */ + stb r21,PACAHRDWINTCOUNT(r13) /* */ bne 2f /* */ mr r14,r1 /* preserve current r1 */ - ld r1,PACAHRDWINTSTACK(r20) /* */ + ld r1,PACAHRDWINTSTACK(r13) /* */ std r14,0(r1) /* set the back chain */ bl .do_IRQ - lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ + lbz r22,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ cmp 0,r22,r21 /* debug test */ bne 3f subi r21,r21,1 - stb r21,PACAHRDWINTCOUNT(r20) /* */ + stb r21,PACAHRDWINTCOUNT(r13) /* */ mr r1,r14 /* */ b .ret_from_except +#endif 2: bl .do_IRQ - lbz r22,PACAHRDWINTCOUNT(r20) /* get hardware interrupt cnt */ +#if 0 + lbz r22,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ cmp 0,r22,r21 /* debug test */ bne 3f /* */ subi r21,r21,1 /* decr hardware interrupt cnt*/ - stb r21,PACAHRDWINTCOUNT(r20) /* */ + stb r21,PACAHRDWINTCOUNT(r13) /* */ +#endif b .ret_from_except @@ -804,6 +818,7 @@ /* * r3 contains the faulting address * r4 contains the required access permissions + * r5 contains the trap number * * at return r3 = 0 for success */ @@ -852,11 +867,13 @@ ld r22,8(r21) /* get SRR1 */ andi. r22,r22,MSR_PR /* check if from user */ bne+ stab_bolted_user_return /* from user, send the error on up */ +#if 0 li r3,0 #ifdef CONFIG_XMON bl .xmon #endif 1: b 1b +#endif 2: /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ mfspr r21,DAR @@ -1021,7 +1038,18 @@ #ifndef CONFIG_PPC_ISERIES ori r20,r20,256 /* map kernel region with large ptes */ #endif - + + /* + * XXX we should handle this in the exception exit path in 2.5, + * we need to make this path quick - Anton + */ + /* Invalidate the old entry */ + slbmfee r21,r22 + lis r23,-2049 + ori r23,r23,65535 + and r21,r21,r23 + slbie r21 + /* Put together the esid portion of the entry. */ mfspr r21,DAR /* Get the new esid */ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */ @@ -1099,30 +1127,33 @@ * Indicate that r1 contains the kernel stack and * get the Kernel TOC and CURRENT pointers from the paca */ - mfspr r23,SPRG3 /* Get PACA */ - std r22,PACAKSAVE(r23) /* r1 is now kernel sp */ - ld r2,PACATOC(r23) /* Get Kernel TOC pointer */ + std r22,PACAKSAVE(r13) /* r1 is now kernel sp */ + ld r2,PACATOC(r13) /* Get Kernel TOC pointer */ /* * If from user state, update THREAD.regs */ beq 2f /* Modify THREAD.regs if from user */ addi r24,r1,STACK_FRAME_OVERHEAD - std r24,THREAD+PT_REGS(r13) + ld r22, PACACURRENT(r13) + std r24,THREAD+PT_REGS(r22) 2: SET_REG_TO_CONST(r22, MSR_KERNEL) #ifdef DO_SOFT_DISABLE - stb r20,PACAPROCENABLED(r23) /* possibly soft enable */ +#warning FIX ISERIES + stb r20,PACAPROCENABLED(r13) /* possibly soft enable */ ori r22,r22,MSR_EE /* always hard enable */ #else rldimi r22,r20,15,48 /* Insert desired EE value */ #endif - mtmsrd r22 + mtmsrd r22,1 blr - +/* + * Kernel profiling with soft disable on iSeries + */ do_profile: ld r22,8(r21) /* Get SRR1 */ andi. r22,r22,MSR_PR /* Test if in kernel */ @@ -1158,20 +1189,20 @@ /* Set up a paca value for this processor. */ LOADADDR(r24, paca) /* Get base vaddr of paca array */ - mulli r25,r3,PACA_SIZE /* Calculate vaddr of right paca */ - add r25,r25,r24 /* for this processor. */ + mulli r13,r3,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r13,r24 /* for this processor. */ - mtspr SPRG3,r25 /* Save vaddr of paca in SPRG3 */ + mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ mr r24,r3 /* __secondary_start needs cpu# */ 1: HMT_LOW - lbz r23,PACAPROCSTART(r25) /* Test if this processor should */ + lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ /* start. */ sync /* Create a temp kernel stack for use before relocation is on. */ - mr r1,r25 + mr r1,r13 addi r1,r1,PACAGUARD addi r1,r1,0x1000 subi r1,r1,STACK_FRAME_OVERHEAD @@ -1400,7 +1431,8 @@ #endif /* CONFIG_SMP */ /* enable use of FP after return */ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 - addi r5,r13,THREAD /* Get THREAD */ + ld r4, PACACURRENT(r13) + addi r5,r4,THREAD /* Get THREAD */ lfd fr0,THREAD_FPSCR-4(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) @@ -1420,8 +1452,7 @@ ori r3,r3,MSR_FP std r3,_MSR(r1) /* enable use of FP after return */ LOADADDR(r3,86f) - mfspr r4,SPRG3 /* Get PACA */ - ld r4,PACACURRENT(r4) /* current */ + ld r4,PACACURRENT(r13) /* current */ ld r5,_NIP(r1) b .ret_from_except 86: .string "floating point used in kernel (task=%p, pc=%x)\n" @@ -1470,7 +1501,7 @@ * On entry the following are set: * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries * r24 = cpu# (in Linux terms) - * r25 = paca virtual address + * r13 = paca virtual address * SPRG3 = paca virtual address */ _GLOBAL(__secondary_start) @@ -1482,10 +1513,10 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 - std r2,PACATOC(r25) + std r2,PACATOC(r13) li r6,0 - std r6,PACAKSAVE(r25) - stb r6,PACAPROCENABLED(r25) + std r6,PACAKSAVE(r13) + stb r6,PACAPROCENABLED(r13) #ifndef CONFIG_PPC_ISERIES /* Initialize the page table pointer register. */ @@ -1494,12 +1525,9 @@ mtspr SDR1,r6 /* set the htab location */ #endif /* Initialize the first segment table (or SLB) entry */ - ld r3,PACASTABVIRT(r25) /* get addr of segment table */ + ld r3,PACASTABVIRT(r13) /* get addr of segment table */ bl .stab_initialize - /* load current into r13 */ - ld r13,PACACURRENT(r25) - /* Initialize the kernel stack. Just a repeat for iSeries. */ LOADADDR(r3,current_set) sldi r28,r24,3 /* get current_set[cpu#] */ @@ -1507,7 +1535,7 @@ addi r1,r1,THREAD_SIZE subi r1,r1,STACK_FRAME_OVERHEAD - ld r3,PACASTABREAL(r25) /* get raddr of segment table */ + ld r3,PACASTABREAL(r13) /* get raddr of segment table */ ori r4,r3,1 /* turn on valid bit */ #ifdef CONFIG_PPC_ISERIES @@ -1517,7 +1545,17 @@ ori r3,r3,4 /* 0x8000000000000004 */ sc /* HvCall_setASR */ #else + /* set the ASR */ + addi r3,0,0x4000 /* r3 = ptr to naca */ + lhz r3,PLATFORM(r3) /* r3 = platform flags */ + cmpldi r3,PLATFORM_PSERIES_LPAR + bne 98f + li r3,H_SET_ASR /* hcall = H_SET_ASR */ + HSC /* Invoking hcall */ + b 99f +98: /* This is not a hypervisor machine */ mtasr r4 /* set the stab location */ +99: #endif li r7,0 mtlr r7 @@ -1640,23 +1678,49 @@ /* Get the pointer to the segment table which is used by */ /* stab_initialize */ - li r27,0x4000 - ld r6,PACA(r27) /* Get the base paca pointer */ - sub r6,r6,r26 /* convert to physical addr */ - mtspr SPRG3,r6 /* PPPBBB: Temp... -Peter */ - ld r3,PACASTABREAL(r6) + LOADADDR(r27, boot_cpuid) + sub r27,r27,r26 + lwz r27,0(r27) + + LOADADDR(r24, paca) /* Get base vaddr of paca array */ + mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r13,r24 /* for this processor. */ + sub r13,r13,r26 /* convert to physical addr */ + + mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ + li r3,0x5000 + std r3,PACASTABREAL(r13) + LOADADDR(r24, __start_stab) + std r24,PACASTABVIRT(r13) ori r4,r3,1 /* turn on valid bit */ + + /* set the ASR */ + addi r3,0,0x4000 /* r3 = ptr to naca */ + lhz r3,PLATFORM(r3) /* r3 = platform flags */ + cmpldi r3,PLATFORM_PSERIES_LPAR + bne 98f + li r3,H_SET_ASR /* hcall = H_SET_ASR */ + HSC /* Invoking hcall */ + b 99f +98: /* This is not a hypervisor machine */ mtasr r4 /* set the stab location */ +99: + mfspr r6,SPRG3 + ld r3,PACASTABREAL(r6) /* restore r3 for stab_initialize */ /* Initialize an initial memory mapping and turn on relocation. */ bl .stab_initialize bl .htab_initialize - LOADADDR(r6,_SDR1) + addi r3,0,0x4000 /* r3 = ptr to naca */ + lhz r3,PLATFORM(r3) /* r3 = platform flags */ + cmpldi r3,PLATFORM_PSERIES + bne 98f + LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 ld r6,0(r6) /* get the value of _SDR1 */ mtspr SDR1,r6 /* set the htab location */ - +98: LOADADDR(r3,.start_here_common) SET_REG_TO_CONST(r4, MSR_KERNEL) mtspr SRR0,r3 @@ -1705,18 +1769,21 @@ addi r8,r8,0x4000 std r8,0(r9) /* set the value of the naca ptr */ - LOADADDR(r4,naca) /* Get naca ptr address */ - ld r4,0(r4) /* Get the location of the naca */ - ld r4,PACA(r4) /* Get the base paca pointer */ - mtspr SPRG3,r4 + LOADADDR(r26, boot_cpuid) + lwz r26,0(r26) + + LOADADDR(r24, paca) /* Get base vaddr of paca array */ + mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r13,r24 /* for this processor. */ + mtspr SPRG3,r13 /* ptr to current */ - LOADADDR(r13,init_task) - std r13,PACACURRENT(r4) + LOADADDR(r4,init_task) + std r4,PACACURRENT(r13) - std r2,PACATOC(r4) + std r2,PACATOC(r13) li r5,0 - std r0,PACAKSAVE(r4) + std r0,PACAKSAVE(r13) /* ptr to hardware interrupt stack for processor 0 */ LOADADDR(r3, hardware_int_paca0) @@ -1725,10 +1792,10 @@ subi r5,r5,STACK_FRAME_OVERHEAD add r3,r3,r5 - std r3,PACAHRDWINTSTACK(r4) + std r3,PACAHRDWINTSTACK(r13) li r3,0 - stb r3,PACAHRDWINTCOUNT(r4) + stb r3,PACAHRDWINTCOUNT(r13) /* Restore the parms passed in from the bootloader. */ mr r3,r31 @@ -1742,6 +1809,7 @@ /* Load up the kernel context */ 5: #ifdef DO_SOFT_DISABLE +#warning FIX ISERIES mfspr r4,SPRG3 li r5,0 stb r5,PACAPROCENABLED(r4) /* Soft Disabled */ @@ -1849,10 +1917,10 @@ hardware_int_paca0: .space 8*4096 -/* 1 page segment table per cpu (max 48, cpu0 allocated at 0x5000) */ +/* 1 page segment table per cpu (max 48) */ .globl stab_array stab_array: - .space 4096 * (48 - 1) + .space 4096 * 48 /* * This space gets a copy of optional info passed to us by the bootstrap diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/htab.c Wed Jul 24 14:03:38 2002 @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -45,9 +44,8 @@ #include #include #include -#ifdef CONFIG_PPC_EEH #include -#endif +#include /* * Note: pte --> Linux PTE @@ -141,7 +139,7 @@ mask = pteg_count-1; /* XXX we currently map kernel text rw, should fix this */ - if (__is_processor(PV_POWER4) && _naca->physicalMemorySize > 256*MB) { + if (cpu_has_largepage() && _naca->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, mask, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, @@ -196,7 +194,7 @@ * to be valid via Linux page tables, return 1. If handled return 0 */ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - pte_t *ptep) + pte_t *ptep, unsigned long trap) { unsigned long va, vpn; unsigned long newpp, prpn; @@ -212,7 +210,7 @@ * If no pte found or not present, send the problem up to * do_page_fault */ - if (!ptep || !pte_present(*ptep)) + if (unlikely(!ptep || !pte_present(*ptep))) return 1; /* @@ -220,7 +218,7 @@ * prevented then send the problem up to do_page_fault. */ access |= _PAGE_PRESENT; - if (access & ~(pte_val(*ptep))) + if (unlikely(access & ~(pte_val(*ptep)))) return 1; /* @@ -245,8 +243,26 @@ newpp = computeHptePP(pte_val(new_pte)); +#define PPC64_HWNOEXEC (1 << 2) + + /* We do lazy icache flushing on cpus that support it */ + if (unlikely(cpu_has_noexecute() && pfn_valid(pte_pfn(new_pte)))) { + struct page *page = pte_page(new_pte); + + /* page is dirty */ + if (!PageReserved(page) && + !test_bit(PG_arch_1, &page->flags)) { + if (trap == 0x400) { + __flush_dcache_icache(page_address(page)); + set_bit(PG_arch_1, &page->flags); + } else { + newpp |= PPC64_HWNOEXEC; + } + } + } + /* Check if pte already has an hpte (case 2) */ - if (pte_val(old_pte) & _PAGE_HASHPTE) { + if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) { /* There MIGHT be an HPTE for this pte */ unsigned long hash, slot, secondary; @@ -266,7 +282,7 @@ *ptep = new_pte; } - if (!(pte_val(old_pte) & _PAGE_HASHPTE)) { + if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) { /* XXX fix large pte flag */ unsigned long hash = hpt_hash(vpn, 0); unsigned long hpte_group; @@ -318,7 +334,7 @@ return 0; } -int hash_page(unsigned long ea, unsigned long access) +int hash_page(unsigned long ea, unsigned long access, unsigned long trap) { void *pgdir; unsigned long vsid; @@ -346,13 +362,11 @@ mm = &init_mm; vsid = get_kernel_vsid(ea); break; -#ifdef CONFIG_PPC_EEH case IO_UNMAPPED_REGION_ID: udbg_printf("EEH Error ea = 0x%lx\n", ea); PPCDBG_ENTER_DEBUGGER(); panic("EEH Error ea = 0x%lx\n", ea); break; -#endif case KERNEL_REGION_ID: /* * As htab_initialize is now, we shouldn't ever get here since @@ -379,7 +393,7 @@ */ spin_lock(&mm->page_table_lock); ptep = find_linux_pte(pgdir, ea); - ret = __hash_page(ea, access, vsid, ptep); + ret = __hash_page(ea, access, vsid, ptep, trap); spin_unlock(&mm->page_table_lock); return ret; @@ -419,12 +433,11 @@ ppc_md.flush_hash_range(context, number, local); } else { int i; - struct tlb_batch_data *ptes = - &tlb_batch_array[smp_processor_id()][0]; + struct ppc64_tlb_batch *batch = + &ppc64_tlb_batch[smp_processor_id()]; - for (i = 0; i < number; i++) { - flush_hash_page(context, ptes->addr, ptes->pte, local); - ptes++; - } + for (i = 0; i < number; i++) + flush_hash_page(context, batch->addr[i], batch->pte[i], + local); } } diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c --- a/arch/ppc64/kernel/iSeries_pci.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/iSeries_pci.c Wed Jul 24 14:03:39 2002 @@ -21,7 +21,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/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c --- a/arch/ppc64/kernel/iSeries_pci_reset.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/iSeries_pci_reset.c Wed Jul 24 14:03:39 2002 @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/iSeries_setup.c Wed Jul 24 14:03:39 2002 @@ -258,7 +258,7 @@ { unsigned long i; unsigned long mem_blocks = 0; - if ( __is_processor( PV_POWER4 ) ) + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) mem_blocks = iSeries_process_Regatta_mainstore_vpd( mb_array, max_entries ); else mem_blocks = iSeries_process_Condor_mainstore_vpd( mb_array, max_entries ); diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/irq.c Wed Jul 24 14:03:38 2002 @@ -1,6 +1,4 @@ /* - * - * * arch/ppc/kernel/irq.c * * Derived from arch/i386/kernel/irq.c @@ -25,7 +23,6 @@ * should be easier. */ - #include #include #include @@ -81,7 +78,7 @@ * this needs to be removed. * -- Cort */ -#define IRQ_KMALLOC_ENTRIES 8 +#define IRQ_KMALLOC_ENTRIES 16 static int cache_bitmask = 0; static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES]; extern int mem_init_done; @@ -168,6 +165,20 @@ return 0; } +#ifdef CONFIG_SMP + +inline void synchronize_irq(unsigned int irq) +{ + while (irq_desc[irq].status & IRQ_INPROGRESS) { + barrier(); + cpu_relax(); + } +} + +#endif /* CONFIG_SMP */ + +/* XXX Make this into free_irq() - Anton */ + /* This could be promoted to a real free_irq() ... */ static int do_free_irq(int irq, void* dev_id) @@ -195,11 +206,8 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif + synchronize_irq(irq); irq_kfree(action); return 0; } @@ -296,12 +304,7 @@ void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } + synchronize_irq(irq); } /** @@ -346,8 +349,10 @@ struct irqaction * action; seq_printf(p, " "); - for (j=0; jflags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -391,7 +397,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); } #ifdef CONFIG_SMP @@ -403,7 +409,7 @@ } ____cacheline_aligned irq_balance_t; static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned - = { [ 0 ... NR_IRQS-1 ] = { 1, 0 } }; + = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } }; #define IDLE_ENOUGH(cpu,now) \ (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > ((HZ/100)+1))) @@ -425,14 +431,14 @@ inside: if (direction == 1) { cpu++; - if (cpu >= smp_num_cpus) + if (cpu >= NR_CPUS) cpu = 0; } else { cpu--; if (cpu == -1) - cpu = smp_num_cpus-1; + cpu = NR_CPUS-1; } - } while (!IRQ_ALLOWED(cpu,allowed_mask) || + } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || (search_idle && !IDLE_ENOUGH(cpu,now))); return cpu; @@ -474,7 +480,9 @@ int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; - balance_irq(irq); + /* XXX This causes bad performance and lockups on XICS - Anton */ + if (naca->interrupt_controller == IC_OPEN_PIC) + balance_irq(irq); kstat.irqs[cpu][irq]++; spin_lock(&desc->lock); @@ -566,7 +574,7 @@ struct ItLpQueue *lpq; #endif - irq_enter(cpu); + irq_enter(); #ifdef CONFIG_PPC_ISERIES lpaca = get_paca(); @@ -597,7 +605,7 @@ ppc_spurious_interrupts++; #endif - irq_exit(cpu); + irq_exit(); #ifdef CONFIG_PPC_ISERIES if (lpaca->xLpPaca.xIntDword.xFields.xDecrInt) { @@ -640,156 +648,6 @@ ppc_md.init_IRQ(); if(ppc_md.init_ras_IRQ) ppc_md.init_ras_IRQ(); } - -#ifdef CONFIG_SMP -unsigned char global_irq_holder = NO_PROC_ID; - -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 < smp_num_cpus; i++) - printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]); - printk("]\nbh: %d [ ", - (spin_is_locked(&global_bh_lock) ? 1 : 0)); - for (i = 0; i < smp_num_cpus; i++) - printk("%u ", local_bh_count(i)); - printk("]\n"); -} - -#define MAXCOUNT 10000000 - -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); - } - __sti(); - barrier(); - __cli(); - } - 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; - - __save_flags(flags); - if (flags & (1UL << 15)) { - int cpu = smp_processor_id(); - __cli(); - if (!local_irq_count(cpu)) - get_irqlock(cpu); - } -} - -void __global_sti(void) -{ - int cpu = smp_processor_id(); - - if (!local_irq_count(cpu)) - release_irqlock(cpu); - __sti(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - - __save_flags(flags); - local_enabled = (flags >> 15) & 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) -{ - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - __cli(); - break; - case 3: - __sti(); - break; - default: - printk("global_restore_flags: %016lx caller %p\n", - flags, __builtin_return_address(0)); - } -} - -#endif /* CONFIG_SMP */ static struct proc_dir_entry * root_irq_dir; static struct proc_dir_entry * irq_dir [NR_IRQS]; diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/misc.S Wed Jul 24 14:03:37 2002 @@ -66,6 +66,7 @@ #ifdef CONFIG_PPC_ISERIES /* unsigned long __no_use_save_flags(void) */ _GLOBAL(__no_use_save_flags) +#warning FIX ISERIES mfspr r4,SPRG3 lbz r3,PACAPROCENABLED(r4) blr @@ -78,6 +79,7 @@ * sense anyway. * -- Cort */ +#warning FIX ISERIES mfspr r6,SPRG3 lbz r5,PACAPROCENABLED(r6) /* Check if things are setup the way we want _already_. */ @@ -99,6 +101,7 @@ blr _GLOBAL(__no_use_cli) +#warning FIX ISERIES mfspr r5,SPRG3 lbz r3,PACAPROCENABLED(r5) li r4,0 @@ -106,6 +109,7 @@ blr /* Done */ _GLOBAL(__no_use_sti) +#warning FIX ISERIES mfspr r6,SPRG3 li r3,1 stb r3,PACAPROCENABLED(r6) diff -Nru a/arch/ppc64/kernel/mk_defs.c b/arch/ppc64/kernel/mk_defs.c --- a/arch/ppc64/kernel/mk_defs.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/mk_defs.c Wed Jul 24 14:03:38 2002 @@ -14,7 +14,6 @@ */ #include -#include #include #include #include @@ -48,7 +47,6 @@ DEFINE(THREAD_SHIFT, THREAD_SHIFT); DEFINE(THREAD_SIZE, THREAD_SIZE); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(_TIF_32BIT, _TIF_32BIT); /* task_struct->thread */ DEFINE(THREAD, offsetof(struct task_struct, thread)); @@ -68,6 +66,7 @@ DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage)); DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size)); + DEFINE(PLATFORM, offsetof(struct naca_struct, platform)); /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); diff -Nru a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c --- a/arch/ppc64/kernel/nvram.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc64/kernel/nvram.c Wed Jul 24 14:03:35 2002 @@ -99,11 +99,11 @@ } struct file_operations nvram_fops = { - owner: THIS_MODULE, - llseek: nvram_llseek, - read: read_nvram, - write: write_nvram, - ioctl: nvram_ioctl, + .owner = THIS_MODULE, + .llseek = nvram_llseek, + .read = read_nvram, + .write = write_nvram, + .ioctl = nvram_ioctl, }; static struct miscdevice nvram_dev = { diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c --- a/arch/ppc64/kernel/open_pic.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/open_pic.c Wed Jul 24 14:03:38 2002 @@ -33,7 +33,6 @@ static volatile struct OpenPIC *OpenPIC = NULL; u_int OpenPIC_NumInitSenses __initdata = 0; u_char *OpenPIC_InitSenses __initdata = NULL; -extern int use_of_interrupt_tree; void find_ISUs(void); @@ -86,10 +85,10 @@ */ #ifdef CONFIG_SMP #define THIS_CPU Processor[cpu] -#define DECL_THIS_CPU int cpu = hard_smp_processor_id() +#define DECL_THIS_CPU int cpu = smp_processor_id() #define CHECK_THIS_CPU check_arg_cpu(cpu) #else -#define THIS_CPU Processor[hard_smp_processor_id()] +#define THIS_CPU Processor[smp_processor_id()] #define DECL_THIS_CPU #define CHECK_THIS_CPU #endif /* CONFIG_SMP */ @@ -357,7 +356,7 @@ /* SIOint (8259 cascade) is special */ if (offset) { openpic_initirq(0, 8, offset, 1, 1); - openpic_mapirq(0, 1<>= 1) - mask |= (cpumask & 1) << get_hard_smp_processor_id(i); - return mask; -} - void openpic_init_processor(u_int cpumask) { openpic_write(&OpenPIC->Global.Processor_Initialization, - physmask(cpumask)); + cpumask & cpu_online_map); } #ifdef CONFIG_SMP @@ -554,7 +540,7 @@ CHECK_THIS_CPU; check_arg_ipi(ipi); openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), - physmask(cpumask)); + cpumask & cpu_online_map); } void openpic_request_IPIs(void) @@ -594,7 +580,7 @@ { #ifdef CONFIG_IRQ_ALL_CPUS int i; - u32 msk = 1 << hard_smp_processor_id(); + u32 msk = 1 << smp_processor_id(); #endif spin_lock(&openpic_setup_lock); @@ -639,7 +625,7 @@ { check_arg_timer(timer); openpic_write(&OpenPIC->Global.Timer[timer].Destination, - physmask(cpumask)); + cpumask & cpu_online_map); } @@ -762,7 +748,7 @@ static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask) { - openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask)); + openpic_mapirq(irq_nr - open_pic_irq_offset, cpumask & cpu_online_map); } #ifdef CONFIG_SMP @@ -775,7 +761,7 @@ * SA_INTERRUPT flag and let them execute with all interrupts OFF. * This would have the side effect of either running cross-CPU * functions with interrupts off, or we can re-enable them explicitely - * with a __sti() in smp_call_function_interrupt(), since + * with a local_irq_enable() in smp_call_function_interrupt(), since * smp_call_function() is protected by a spinlock. * Or maybe we shouldn't set the IRQ_PER_CPU flag on cross-CPU * function calls IPI at all but that would make a special case. diff -Nru a/arch/ppc64/kernel/pSeries_htab.c b/arch/ppc64/kernel/pSeries_htab.c --- a/arch/ppc64/kernel/pSeries_htab.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/pSeries_htab.c Wed Jul 24 14:03:37 2002 @@ -20,6 +20,7 @@ #include #include #include +#include /* * Create a pte. Used during initialization only. @@ -214,7 +215,7 @@ __asm__ __volatile__( "1: ldarx %0,0,%3\n\ - rldimi %0,%2,0,62\n\ + rldimi %0,%2,0,61\n\ stdcx. %0,0,%3\n\ bne 1b" : "=&r" (old), "=m" (*p) @@ -265,8 +266,6 @@ unsigned long vpn, avpn; unsigned long flags; - udbg_printf("updatepp\n"); - if (large) vpn = va >> LARGE_PAGE_SHIFT; else @@ -358,7 +357,7 @@ hptep->dw0.dword0 = 0; /* Invalidate the tlb */ - if (!large && local && __is_processor(PV_POWER4)) { + if (cpu_has_tlbiel() && !large && local) { _tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); @@ -372,31 +371,32 @@ { unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn; int i, j; - unsigned long va_array[MAX_BATCH_FLUSH]; HPTE *hptep; Hpte_dword0 dw0; - struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0]; + struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; /* XXX fix for large ptes */ unsigned long large = 0; + j = 0; for (i = 0; i < number; i++) { - if ((ptes->addr >= USER_START) && (ptes->addr <= USER_END)) - vsid = get_vsid(context, ptes->addr); + if ((batch->addr[i] >= USER_START) && + (batch->addr[i] <= USER_END)) + vsid = get_vsid(context, batch->addr[i]); else - vsid = get_kernel_vsid(ptes->addr); + vsid = get_kernel_vsid(batch->addr[i]); - va = (vsid << 28) | (ptes->addr & 0x0fffffff); - va_array[j] = va; + va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); + batch->vaddr[j] = va; if (large) vpn = va >> LARGE_PAGE_SHIFT; else vpn = va >> PAGE_SHIFT; hash = hpt_hash(vpn, large); - secondary = (pte_val(ptes->pte) & _PAGE_SECONDARY) >> 15; + secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15; if (secondary) hash = ~hash; slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(ptes->pte) & _PAGE_GROUP_IX) >> 12; + slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12; hptep = htab_data.htab + slot; avpn = vpn >> 11; @@ -405,8 +405,6 @@ dw0 = hptep->dw0.dw0; - ptes++; - if ((dw0.avpn != avpn) || !dw0.v) { pSeries_unlock_hpte(hptep); udbg_printf("invalidate missed\n"); @@ -419,14 +417,14 @@ hptep->dw0.dword0 = 0; } - if (!large && local && __is_processor(PV_POWER4)) { + if (cpu_has_tlbiel() && !large && local) { asm volatile("ptesync":::"memory"); for (i = 0; i < j; i++) { asm volatile("\n\ clrldi %0,%0,16\n\ tlbiel %0" - : : "r" (va_array[i]) : "memory" ); + : : "r" (batch->vaddr[i]) : "memory" ); } asm volatile("ptesync":::"memory"); @@ -440,7 +438,7 @@ asm volatile("\n\ clrldi %0,%0,16\n\ tlbie %0" - : : "r" (va_array[i]) : "memory" ); + : : "r" (batch->vaddr[i]) : "memory" ); } asm volatile("eieio; tlbsync; ptesync":::"memory"); diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/pSeries_lpar.c Wed Jul 24 14:03:39 2002 @@ -33,6 +33,7 @@ #include #include #include +#include /* Status return values */ #define H_Success 0 @@ -308,7 +309,7 @@ { unsigned long lpar_rc; - lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu),value); + lpar_rc = plpar_ipi(n_cpu, value); if (lpar_rc != H_Success) { panic(" bad return code qirr -ipi - rc = %lx \n", lpar_rc); } @@ -355,8 +356,13 @@ /* get some more chars. */ inbuflen = 0; rc = plpar_get_term_char(vtermno, &inbuflen, buf); - if (inbuflen == 0 && rc == H_Success) - return -1; + if (rc != H_Success) + inbuflen = 0; /* otherwise inbuflen is garbage */ + } + if (inbuflen <= 0 || inbuflen > 16) { + /* Catch error case as well as other oddities (corruption) */ + inbuflen = 0; + return -1; } ch = buf[0]; for (i = 1; i < inbuflen; i++) /* shuffle them down. */ @@ -646,11 +652,9 @@ { unsigned long lpar_rc; unsigned long flags; - flags = (newpp & 3) | H_AVPN; + flags = (newpp & 7) | H_AVPN; unsigned long vpn = va >> PAGE_SHIFT; - udbg_printf("updatepp\n"); - lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL); if (lpar_rc == H_Not_Found) { @@ -775,15 +779,14 @@ int local) { int i; - struct tlb_batch_data *ptes = - &tlb_batch_array[smp_processor_id()][0]; unsigned long flags; + struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); - for (i = 0; i < number; i++) { - flush_hash_page(context, ptes->addr, ptes->pte, local); - ptes++; - } + + for (i = 0; i < number; i++) + flush_hash_page(context, batch->addr[i], batch->pte[i], local); + spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); } diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/pSeries_pci.c Wed Jul 24 14:03:39 2002 @@ -22,7 +22,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include #include @@ -36,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +69,7 @@ * *****************************************************************************/ #define RTAS_PCI_READ_OP(size, type, nbytes) \ -int __chrp \ +int \ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \ unsigned long returnval = ~0L; \ unsigned long buid; \ @@ -96,7 +94,7 @@ *val = returnval; \ return ret; \ } \ -int __chrp \ +int \ rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \ struct device_node *dn = pci_device_to_OF_node(dev); \ int ret = rtas_read_config_##size(dn, offset, val); \ @@ -105,7 +103,7 @@ } #define RTAS_PCI_WRITE_OP(size, type, nbytes) \ -int __chrp \ +int \ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \ unsigned long buid; \ unsigned int addr; \ @@ -126,7 +124,7 @@ } \ return ret; \ } \ -int __chrp \ +int \ rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \ struct device_node* dn = pci_device_to_OF_node(dev); \ int ret = rtas_write_config_##size(dn, offset, val); \ @@ -515,8 +513,10 @@ /*************************************************************** * Speedwagon + * include Winnipeg as well for the time being. ***************************************************************/ - } else if (strstr(model, "Speedwagon")) { + } else if ((strstr(model, "Speedwagon")) || + (strstr(model, "Winnipeg"))) { PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n"); phb = pci_alloc_pci_controller("PHB SW",phb_type_speedwagon); if (phb == NULL) return NULL; diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/pacaData.c Wed Jul 24 14:03:39 2002 @@ -31,36 +31,36 @@ * processors. The processor VPD array needs one entry per physical * processor (not thread). */ -#define PACAINITDATA(number,start,lpq,asrr,asrv) \ -{ \ - xLpPacaPtr: &paca[number].xLpPaca, \ - xLpRegSavePtr: &paca[number].xRegSav, \ - xPacaIndex: (number), /* Paca Index */ \ - default_decr: 0x00ff0000, /* Initial Decr */ \ - xStab_data: { \ - real: (asrr), /* Real pointer to segment table */ \ - virt: (asrv), /* Virt pointer to segment table */ \ - next_round_robin: 1 /* Round robin index */ \ - }, \ - lpQueuePtr: (lpq), /* &xItLpQueue, */ \ - /* xRtas: { \ - lock: SPIN_LOCK_UNLOCKED \ - }, */ \ - xProcStart: (start), /* Processor start */ \ - xLpPaca: { \ - xDesc: 0xd397d781, /* "LpPa" */ \ - xSize: sizeof(struct ItLpPaca), \ - xFPRegsInUse: 1, \ - xDynProcStatus: 2, \ - xDecrVal: 0x00ff0000, \ - xEndOfQuantum: 0xffffffffffffffff \ - }, \ - xRegSav: { \ - xDesc: 0xd397d9e2, /* "LpRS" */ \ - xSize: sizeof(struct ItLpRegSave) \ - }, \ - exception_sp: \ - (&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \ +#define PACAINITDATA(number,start,lpq,asrr,asrv) \ +{ \ + .xLpPacaPtr = &paca[number].xLpPaca, \ + .xLpRegSavePtr = &paca[number].xRegSav, \ + .xPacaIndex = (number), /* Paca Index */ \ + .default_decr = 0x00ff0000, /* Initial Decr */ \ + .xStab_data = { \ + .real = (asrr), /* Real pointer to segment table */ \ + .virt = (asrv), /* Virt pointer to segment table */ \ + .next_round_robin = 1 /* Round robin index */ \ + }, \ + .lpQueuePtr = (lpq), /* &xItLpQueue, */ \ + /* .xRtas = { \ + .lock = SPIN_LOCK_UNLOCKED \ + }, */ \ + .xProcStart = (start), /* Processor start */ \ + .xLpPaca = { \ + .xDesc = 0xd397d781, /* "LpPa" */ \ + .xSize = sizeof(struct ItLpPaca), \ + .xFPRegsInUse = 1, \ + .xDynProcStatus = 2, \ + .xDecrVal = 0x00ff0000, \ + .xEndOfQuantum = 0xffffffffffffffff \ + }, \ + .xRegSav = { \ + .xDesc = 0xd397d9e2, /* "LpRS" */ \ + .xSize = sizeof(struct ItLpRegSave) \ + }, \ + .exception_sp = \ + (&paca[number].exception_stack[0]) - EXC_FRAME_SIZE, \ } struct paca_struct paca[MAX_PACAS] __page_aligned = { diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c --- a/arch/ppc64/kernel/pci_dn.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/pci_dn.c Wed Jul 24 14:03:38 2002 @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c --- a/arch/ppc64/kernel/pmc.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/pmc.c Wed Jul 24 14:03:36 2002 @@ -59,7 +59,9 @@ stab_faults = stab_capacity_castouts = stab_invalidations = n = 0; if (file == -1) { - for (i = 0; i < smp_num_cpus; i++) { + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; stab_faults += pmc_sw_cpu[i].stab_faults; stab_capacity_castouts += pmc_sw_cpu[i].stab_capacity_castouts; stab_invalidations += pmc_sw_cpu[i].stab_invalidations; diff -Nru a/arch/ppc64/kernel/ppc_asm.h b/arch/ppc64/kernel/ppc_asm.h --- a/arch/ppc64/kernel/ppc_asm.h Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/ppc_asm.h Wed Jul 24 14:03:37 2002 @@ -11,8 +11,6 @@ * 2 of the License, or (at your option) any later version. */ -#include - #include #include "ppc_defs.h" diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/ppc_ksyms.c Wed Jul 24 14:03:36 2002 @@ -86,8 +86,6 @@ EXPORT_SYMBOL(disable_irq_nosync); #ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); -EXPORT_SYMBOL(synchronize_irq); -EXPORT_SYMBOL(smp_num_cpus); #endif /* CONFIG_SMP */ EXPORT_SYMBOL(register_ioctl32_conversion); @@ -212,10 +210,6 @@ EXPORT_SYMBOL(flush_icache_page); EXPORT_SYMBOL(flush_dcache_page); #ifdef CONFIG_SMP -EXPORT_SYMBOL(__global_cli); -EXPORT_SYMBOL(__global_sti); -EXPORT_SYMBOL(__global_save_flags); -EXPORT_SYMBOL(__global_restore_flags); #ifdef CONFIG_PPC_ISERIES EXPORT_SYMBOL(__no_use_restore_flags); EXPORT_SYMBOL(__no_use_save_flags); diff -Nru a/arch/ppc64/kernel/proc_pmc.c b/arch/ppc64/kernel/proc_pmc.c --- a/arch/ppc64/kernel/proc_pmc.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/proc_pmc.c Wed Jul 24 14:03:37 2002 @@ -24,6 +24,10 @@ * End Change Activity */ +#include +#include +#include + #include #include #include @@ -33,12 +37,10 @@ #include #include #include - -#include -#include #include #include #include +#include static int proc_pmc_control_mode = 0; @@ -100,21 +102,26 @@ if (!proc_ppc64_root) return; spin_unlock(&proc_ppc64_lock); -#ifdef CONFIG_PPC_EEH - eeh_init_proc(proc_ppc64_root); -#endif + /* Placeholder for rtas interfaces. */ + rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root); + proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root); proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root); - for (i = 0; i < naca->processorCount; i++) { - sprintf(buf, "cpu%ld", i); - proc_ppc64_pmc_cpu_root[i] = proc_mkdir(buf, proc_ppc64_pmc_root); + for (i = 0; i < NR_CPUS; i++) { + if (cpu_online(i)) { + sprintf(buf, "cpu%ld", i); + proc_ppc64_pmc_cpu_root[i] = + proc_mkdir(buf, proc_ppc64_pmc_root); + } } /* Create directories for the software counters. */ - for (i = 0; i < naca->processorCount; i++) { + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, proc_ppc64_pmc_cpu_root[i]); if (ent) { @@ -153,7 +160,9 @@ } /* Create directories for the hardware counters. */ - for (i = 0; i < naca->processorCount; i++) { + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, proc_ppc64_pmc_cpu_root[i]); if (ent) { @@ -189,7 +198,9 @@ (unsigned long) proc_ppc64_pmc_system_root) { return(-1); } else { - for (i = 0; i < naca->processorCount; i++) { + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; if ((unsigned long)data == (unsigned long)proc_ppc64_pmc_cpu_root[i]) { return(i); @@ -324,6 +335,7 @@ if (!ent) return; ent->nlink = 1; ent->data = (void *)0; + ent->size = 0; ent->read_proc = proc_get_titanTod; ent->write_proc = NULL; @@ -380,9 +392,10 @@ (unsigned long)xItLpQueue.xLpIntCountByType[i] ); } len += sprintf( page+len, "\n events processed by processor:\n" ); - for (i=0; iprocessorCount; ++i) { - len += sprintf( page+len, " CPU%02d %10u\n", - i, paca[i].lpEvent_count ); + for (i = 0; i < NR_CPUS; ++i) { + if (cpu_online(i)) + len += sprintf( page+len, " CPU%02d %10u\n", + i, paca[i].lpEvent_count ); } return pmc_calc_metrics( page, start, off, count, eof, len ); diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/process.c Wed Jul 24 14:03:38 2002 @@ -44,8 +44,6 @@ #include #include -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs); - struct task_struct *last_task_used_math = NULL; struct mm_struct ioremap_mm = { pgd : ioremap_dir @@ -77,7 +75,7 @@ } void -_switch_to(struct task_struct *prev, struct task_struct *new) +__switch_to(struct task_struct *prev, struct task_struct *new) { struct thread_struct *new_thread, *old_thread; unsigned long flags; @@ -99,9 +97,9 @@ new_thread = &new->thread; old_thread = ¤t->thread; - __save_and_cli(flags); + local_irq_save(flags); _switch(old_thread, new_thread); - __restore_flags(flags); + local_irq_restore(flags); } void show_regs(struct pt_regs * regs) @@ -177,9 +175,8 @@ childregs = (struct pt_regs *) sp; *childregs = *regs; if ((childregs->msr & MSR_PR) == 0) { - /* for kernel thread, set `current' and stackptr in new task */ + /* for kernel thread, set stackptr in new task */ childregs->gpr[1] = sp + sizeof(struct pt_regs); - childregs->gpr[13] = (unsigned long) p; p->thread.regs = NULL; /* no user register state */ clear_ti_thread_flag(p->thread_info, TIF_32BIT); #ifdef CONFIG_PPC_ISERIES @@ -300,13 +297,13 @@ void initialize_paca_hardware_interrupt_stack(void) { - extern struct naca_struct *naca; - int i; unsigned long stack; unsigned long end_of_stack =0; - for (i=1; i < naca->processorCount; i++) { + for (i=1; i < NR_CPUS; i++) { + if (!cpu_possible(i)) + continue; /* Carve out storage for the hardware interrupt stack */ stack = __get_free_pages(GFP_KERNEL, get_order(8*PAGE_SIZE)); @@ -326,10 +323,12 @@ * __get_free_pages() might give us a page > KERNBASE+256M which * is mapped with large ptes so we can't set up the guard page. */ - if (__is_processor(PV_POWER4)) + if (cpu_has_largepage()) return; - for (i=0; i < naca->processorCount; i++) { + for (i=0; i < NR_CPUS; i++) { + if (!cpu_possible(i)) + continue; /* set page at the top of stack to be protected - prevent overflow */ end_of_stack = paca[i].xHrdIntStack - (8*PAGE_SIZE - STACK_FRAME_OVERHEAD); ppc_md.hpte_updateboltedpp(PP_RXRX,end_of_stack); diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/prom.c Wed Jul 24 14:03:39 2002 @@ -48,7 +48,6 @@ #define call_yaboot(FUNC,...) do { ; } while (0) #endif -#include #include #include #include @@ -446,9 +445,12 @@ } /* We gotta have at least 1 cpu... */ - if ( (_naca->processorCount = num_cpus) < 1 ) + if (num_cpus < 1) PROM_BUG(); + if (num_cpus > 1) + RELOC(ppc64_is_smp) = 1; + _naca->physicalMemorySize = lmb_phys_mem_size(); if (_naca->platform == PLATFORM_PSERIES) { @@ -478,10 +480,6 @@ _naca->slb_size = 64; #ifdef DEBUG_PROM - prom_print(RELOC("naca->processorCount = 0x")); - prom_print_hex(_naca->processorCount); - prom_print_nl(); - prom_print(RELOC("naca->physicalMemorySize = 0x")); prom_print_hex(_naca->physicalMemorySize); prom_print_nl(); @@ -904,11 +902,13 @@ /* Keep the old logic in tack to avoid regression. */ if (compatible[0] != 0) { if((strstr(compatible, RELOC("python")) == NULL) && - (strstr(compatible, RELOC("Speedwagon")) == NULL)) + (strstr(compatible, RELOC("Speedwagon")) == NULL) && + (strstr(compatible, RELOC("Winnipeg")) == NULL)) continue; } else if (model[0] != 0) { if ((strstr(model, RELOC("ython")) == NULL) && - (strstr(model, RELOC("peedwagon")) == NULL)) + (strstr(model, RELOC("peedwagon")) == NULL) && + (strstr(model, RELOC("innipeg")) == NULL)) continue; } @@ -1045,20 +1045,15 @@ phandle node; unsigned long offset = reloc_offset(); char type[64], *path; - int cpuid = 0; extern void __secondary_hold(void); extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; 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 paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); - /* Initially, we must have one active CPU. */ - _naca->processorCount = 1; - #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); @@ -1118,19 +1113,12 @@ node, path, 255) < 0) continue; - cpuid++; - #ifdef DEBUG_PROM prom_print_nl(); - prom_print(RELOC("cpuid = 0x")); - prom_print_hex(cpuid); - prom_print_nl(); prom_print(RELOC("cpu hw idx = 0x")); prom_print_hex(reg); prom_print_nl(); #endif - _xPaca[cpuid].xHwProcNum = reg; - prom_print(RELOC("starting cpu ")); prom_print(path); @@ -1156,11 +1144,9 @@ prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl(); - prom_print(RELOC(" 3) cpuid = 0x")); - prom_print_hex(cpuid); prom_print_nl(); #endif - call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); + call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg); prom_print(RELOC("...")); for ( i = 0 ; (i < 100000000) && (*acknowledge == ((unsigned long)-1)); i++ ) ; @@ -1172,10 +1158,10 @@ prom_print_nl(); } #endif - if (*acknowledge == cpuid) { + if (*acknowledge == reg) { prom_print(RELOC("ok\n")); /* Set the number of active processors. */ - _naca->processorCount++; + _xPaca[reg].active = 1; } else { prom_print(RELOC("failed: ")); prom_print_hex(*acknowledge); @@ -1189,10 +1175,11 @@ __is_processor(PV_SSTAR)) { prom_print(RELOC(" starting secondary threads\n")); - for (i=0; i < _naca->processorCount ;i++) { - unsigned long threadid = _naca->processorCount*2-1-i; - - if (i == 0) { + for (i = 0; i < NR_CPUS; i += 2) { + if (!_xPaca[i].active) + continue; + + if (i == boot_cpuid) { unsigned long pir = _get_PIR(); if (__is_processor(PV_PULSAR)) { RELOC(hmt_thread_data)[i].pir = @@ -1202,21 +1189,9 @@ pir & 0x3ff; } } - - RELOC(hmt_thread_data)[i].threadid = threadid; -#ifdef DEBUG_PROM - prom_print(RELOC(" cpuid 0x")); - prom_print_hex(i); - prom_print(RELOC(" maps to threadid 0x")); - prom_print_hex(threadid); - prom_print_nl(); - prom_print(RELOC(" pir 0x")); - prom_print_hex(RELOC(hmt_thread_data)[i].pir); - prom_print_nl(); -#endif - _xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1; + _xPaca[i+1].active = 1; + RELOC(hmt_thread_data)[i].threadid = i+1; } - _naca->processorCount *= 2; } else { prom_print(RELOC("Processor is not HMT capable\n")); } @@ -1373,7 +1348,9 @@ cpu_pkg, RELOC("reg"), &getprop_rval, sizeof(getprop_rval)); _prom->cpu = (int)(unsigned long)getprop_rval; - _xPaca[0].xHwProcNum = _prom->cpu; + _xPaca[_prom->cpu].active = 1; + RELOC(cpu_online_map) = 1 << _prom->cpu; + RELOC(boot_cpuid) = _prom->cpu; #ifdef DEBUG_PROM prom_print(RELOC("Booting CPU hw index = 0x")); @@ -1409,7 +1386,7 @@ * following, regardless of whether we have an SMP * kernel or not. */ - if ( _naca->processorCount > 1 ) + if (RELOC(ppc64_is_smp)) prom_hold_cpus(mem); mem = check_display(mem); @@ -2110,7 +2087,7 @@ /* * Returns all nodes linked together */ -struct device_node * __openfirmware +struct device_node * find_all_nodes(void) { struct device_node *head, **prevp, *np; @@ -2235,7 +2212,7 @@ /* * Add a property to a node */ -void __openfirmware +void prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -2247,7 +2224,7 @@ } #if 0 -void __openfirmware +void print_properties(struct device_node *np) { struct property *pp; diff -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c --- a/arch/ppc64/kernel/ptrace.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/ptrace.c Wed Jul 24 14:03:37 2002 @@ -1,5 +1,5 @@ /* - * linux/arch/ppc/kernel/ptrace.c + * linux/arch/ppc64/kernel/ptrace.c * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -30,11 +30,7 @@ #include #include #include - -/* - * Set of msr bits that gdb can change on behalf of a process. - */ -#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) +#include /* * does not yet catch signals sent when the child dies. @@ -42,48 +38,6 @@ */ /* - * Get contents of register REGNO in task TASK. - */ -static inline unsigned long get_reg(struct task_struct *task, int regno) -{ - if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)) - return ((unsigned long *)task->thread.regs)[regno]; - return (0); -} - -/* - * Write contents of register REGNO in task TASK. - */ -static inline int put_reg(struct task_struct *task, int regno, - unsigned long data) -{ - if (regno < PT_SOFTE) { - if (regno == PT_MSR) - data = (data & MSR_DEBUGCHANGE) - | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); - ((unsigned long *)task->thread.regs)[regno] = data; - return 0; - } - return -EIO; -} - -static inline void -set_single_step(struct task_struct *task) -{ - struct pt_regs *regs = task->thread.regs; - if (regs != NULL) - regs->msr |= MSR_SE; -} - -static inline void -clear_single_step(struct task_struct *task) -{ - struct pt_regs *regs = task->thread.regs; - if (regs != NULL) - regs->msr &= ~MSR_SE; -} - -/* * Called by kernel/ptrace.c when detaching.. * * Make sure single step bits etc are not set. @@ -148,16 +102,17 @@ /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { - unsigned long index, tmp; + unsigned long index; + unsigned long tmp; ret = -EIO; /* convert to index and check */ index = (unsigned long) addr >> 3; - if ((addr & 7) || index > PT_FPSCR) + if ((addr & 7) || (index > PT_FPSCR)) break; if (index < PT_FPR0) { - tmp = get_reg(child, (int) index); + tmp = get_reg(child, (int)index); } else { if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); @@ -171,7 +126,8 @@ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: ret = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + if (access_process_vm(child, addr, &data, sizeof(data), 1) + == sizeof(data)) break; ret = -EIO; break; @@ -183,7 +139,7 @@ ret = -EIO; /* convert to index and check */ index = (unsigned long) addr >> 3; - if ((addr & 7) || index > PT_FPSCR) + if ((addr & 7) || (index > PT_FPSCR)) break; if (index == PT_ORIG_R3) @@ -216,11 +172,11 @@ break; } -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ + /* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ case PTRACE_KILL: { ret = 0; if (child->state == TASK_ZOMBIE) /* already dead */ @@ -249,56 +205,50 @@ ret = ptrace_detach(child, data); break; - case PPC_PTRACE_GETREGS: - { /* Get GPRs 0 - 31. */ + case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ u64 tmp; u64 cntr; + ret = 0; - for (cntr=0; cntr<32 && ret==0; ++cntr) - { + for (cntr=0; cntr<32 && ret==0; ++cntr) { tmp = ((u64*)child->thread.regs)[cntr]; ret = put_user(tmp, (u64*)(data+cntr)); } break; } - case PPC_PTRACE_SETREGS: - { /* Set GPRs 0 - 31. */ + case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ u64 cntr; + ret = 0; for (cntr=0; cntr<32 && ret==0; ++cntr) - { ret = put_reg(child, cntr, *(u64*)(data+cntr)); - } break; } - case PPC_PTRACE_GETFPREGS: - { /* Get FPRs 0 - 31. */ + case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ u64 tmp; u64 cntr; + ret = -EIO; if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); ret = 0; - for (cntr=0; cntr<32 && ret==0; ++cntr) - { + for (cntr=0; cntr<32 && ret==0; ++cntr) { tmp = ((u64*)child->thread.fpr)[cntr]; ret = put_user(tmp, (u64*)(data+cntr)); } break; } - case PPC_PTRACE_SETFPREGS: - { /* Get FPRs 0 - 31. */ + case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ u64 cntr; + ret = -EIO; if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); for (cntr=0; cntr<32; ++cntr) - { ((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr); - } ret = 0; break; } @@ -334,4 +284,3 @@ current->exit_code = 0; } } - diff -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c --- a/arch/ppc64/kernel/ptrace32.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc64/kernel/ptrace32.c Wed Jul 24 14:03:35 2002 @@ -1,5 +1,5 @@ /* - * linux/arch/ppc/kernel/ptrace32.c + * linux/arch/ppc64/kernel/ptrace32.c * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -30,64 +30,18 @@ #include #include #include - -/* - * Set of msr bits that gdb can change on behalf of a process. - */ -#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) +#include /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. */ -/* - * Get contents of register REGNO in task TASK. - */ -static inline unsigned long get_reg(struct task_struct *task, int regno) -{ - if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)) - return ((unsigned long *)task->thread.regs)[regno]; - return (0); -} - -/* - * Write contents of register REGNO in task TASK. - * (Put DATA into task TASK's register REGNO.) - */ -static inline int put_reg(struct task_struct *task, int regno, unsigned long data) -{ - if (regno < PT_SOFTE) - { - if (regno == PT_MSR) - data = (data & MSR_DEBUGCHANGE) | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); - ((unsigned long *)task->thread.regs)[regno] = data; - return 0; - } - return -EIO; -} - -static inline void -set_single_step(struct task_struct *task) -{ - struct pt_regs *regs = task->thread.regs; - if (regs != NULL) - regs->msr |= MSR_SE; -} - -static inline void -clear_single_step(struct task_struct *task) -{ - struct pt_regs *regs = task->thread.regs; - if (regs != NULL) - regs->msr &= ~MSR_SE; -} - int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) { struct task_struct *child; - int ret = -EPERM; - + int ret = -EPERM; + lock_kernel(); if (request == PTRACE_TRACEME) { /* are we already being traced? */ @@ -120,92 +74,95 @@ if (ret < 0) goto out_tsk; - switch (request) - { - /* Read word at location ADDR */ + switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - { - unsigned int tmp_mem_value; + case PTRACE_PEEKDATA: { + unsigned int tmp; int copied; - copied = access_process_vm(child, addr, &tmp_mem_value, sizeof(tmp_mem_value), 0); + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); ret = -EIO; - if (copied != sizeof(tmp_mem_value)) + if (copied != sizeof(tmp)) break; - ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". + ret = put_user(tmp, (u32*)data); break; } - /* Read 4 bytes of the other process' storage */ - /* data is a pointer specifying where the user wants the 4 bytes copied into */ - /* addr is a pointer in the user's storage that contains an 8 byte address in the other process of the 4 bytes that is to be read */ - /* (this is run in a 32-bit process looking at a 64-bit process) */ - /* when I and D space are separate, these will need to be fixed. */ + /* + * Read 4 bytes of the other process' storage + * data is a pointer specifying where the user wants the + * 4 bytes copied into + * addr is a pointer in the user's storage that contains an 8 byte + * address in the other process of the 4 bytes that is to be read + * (this is run in a 32-bit process looking at a 64-bit process) + * when I and D space are separate, these will need to be fixed. + */ case PPC_PTRACE_PEEKTEXT_3264: - case PPC_PTRACE_PEEKDATA_3264: - { - u32 tmp_mem_value; - int copied; + case PPC_PTRACE_PEEKDATA_3264: { + u32 tmp; + int copied; u32* addrOthers; ret = -EIO; /* Get the addr in the other process that we want to read */ - if (get_user(addrOthers,(u32**)addr) != 0) + if (get_user(addrOthers, (u32**)addr) != 0) break; - copied = access_process_vm(child, (u64)addrOthers, &tmp_mem_value, sizeof(tmp_mem_value), 0); - if (copied != sizeof(tmp_mem_value)) + copied = access_process_vm(child, (u64)addrOthers, &tmp, + sizeof(tmp), 0); + if (copied != sizeof(tmp)) break; - ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". + ret = put_user(tmp, (u32*)data); break; } /* Read a register (specified by ADDR) out of the "user area" */ case PTRACE_PEEKUSR: { int index; - unsigned int reg32bits; - unsigned long tmp_reg_value; + unsigned long tmp; ret = -EIO; /* convert to index and check */ index = (unsigned long) addr >> 2; - if ((addr & 3) || index > PT_FPSCR32) + if ((addr & 3) || (index > PT_FPSCR32)) break; if (index < PT_FPR0) { - tmp_reg_value = get_reg(child, index); + tmp = get_reg(child, index); } else { if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); - /* the user space code considers the floating point to be - * an array of unsigned int (32 bits) - the index passed - * in is based on this assumption. + /* + * the user space code considers the floating point + * to be an array of unsigned int (32 bits) - the + * index passed in is based on this assumption. */ - tmp_reg_value = ((unsigned int *)child->thread.fpr)[index - PT_FPR0]; + tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0]; } - reg32bits = tmp_reg_value; - ret = put_user(reg32bits, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". + ret = put_user((unsigned int)tmp, (u32*)data); break; } - /* Read 4 bytes out of the other process' pt_regs area */ - /* data is a pointer specifying where the user wants the 4 bytes copied into */ - /* addr is the offset into the other process' pt_regs structure that is to be read */ - /* (this is run in a 32-bit process looking at a 64-bit process) */ - case PPC_PTRACE_PEEKUSR_3264: - { + /* + * Read 4 bytes out of the other process' pt_regs area + * data is a pointer specifying where the user wants the + * 4 bytes copied into + * addr is the offset into the other process' pt_regs structure + * that is to be read + * (this is run in a 32-bit process looking at a 64-bit process) + */ + case PPC_PTRACE_PEEKUSR_3264: { u32 index; u32 reg32bits; - u64 tmp_reg_value; + u64 tmp; u32 numReg; u32 part; ret = -EIO; /* Determine which register the user wants */ - index = (u64)addr >> 2; /* Divide addr by 4 */ + index = (u64)addr >> 2; numReg = index / 2; /* Determine which part of the register the user wants */ if (index % 2) @@ -217,117 +174,120 @@ if ((addr & 3) || numReg > PT_FPSCR) break; - if (numReg >= PT_FPR0) - { + if (numReg >= PT_FPR0) { if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); - } - tmp_reg_value = get_reg(child, numReg); - reg32bits = ((u32*)&tmp_reg_value)[part]; - ret = put_user(reg32bits, (u32*)data); /* copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". */ + if (numReg == PT_FPSCR) + tmp = ((unsigned int *)child->thread.fpscr); + else + tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; + } else { /* register within PT_REGS struct */ + tmp = get_reg(child, numReg); + } + reg32bits = ((u32*)&tmp)[part]; + ret = put_user(reg32bits, (u32*)data); break; } - /* Write the word at location ADDR */ /* If I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: { - unsigned int tmp_value_to_write; - tmp_value_to_write = data; + unsigned int tmp; + tmp = data; ret = 0; - if (access_process_vm(child, addr, &tmp_value_to_write, sizeof(tmp_value_to_write), 1) == sizeof(tmp_value_to_write)) + if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) + == sizeof(tmp)) break; ret = -EIO; break; } - /* Write 4 bytes into the other process' storage */ - /* data is the 4 bytes that the user wants written */ - /* addr is a pointer in the user's storage that contains an 8 byte address in the other process where the 4 bytes that is to be written */ - /* (this is run in a 32-bit process looking at a 64-bit process) */ - /* when I and D space are separate, these will need to be fixed. */ + /* + * Write 4 bytes into the other process' storage + * data is the 4 bytes that the user wants written + * addr is a pointer in the user's storage that contains an + * 8 byte address in the other process where the 4 bytes + * that is to be written + * (this is run in a 32-bit process looking at a 64-bit process) + * when I and D space are separate, these will need to be fixed. + */ case PPC_PTRACE_POKETEXT_3264: - case PPC_PTRACE_POKEDATA_3264: - { - u32 tmp_value_to_write = data; + case PPC_PTRACE_POKEDATA_3264: { + u32 tmp = data; u32* addrOthers; - int bytesWritten; /* Get the addr in the other process that we want to write into */ ret = -EIO; - if (get_user(addrOthers,(u32**)addr) != 0) + if (get_user(addrOthers, (u32**)addr) != 0) break; - ret = 0; - bytesWritten = access_process_vm(child, (u64)addrOthers, &tmp_value_to_write, sizeof(tmp_value_to_write), 1); - if (bytesWritten == sizeof(tmp_value_to_write)) + if (access_process_vm(child, (u64)addrOthers, &tmp, + sizeof(tmp), 1) == sizeof(tmp)) break; ret = -EIO; break; } - /* Write DATA into location ADDR within the USER area */ + /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: { unsigned long index; ret = -EIO; - /* convert to index and check */ index = (unsigned long) addr >> 2; - if ((addr & 3) || index > PT_FPSCR32) + if ((addr & 3) || (index > PT_FPSCR32)) break; if (index == PT_ORIG_R3) break; - - if (index < PT_FPR0) { ret = put_reg(child, index, data); } else { if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); - /* the user space code considers the floating point to be - * an array of unsigned int (32 bits) - the index passed - * in is based on this assumption. - */ - + /* + * the user space code considers the floating point + * to be an array of unsigned int (32 bits) - the + * index passed in is based on this assumption. + */ ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data; ret = 0; } break; } - /* Write 4 bytes into the other process' pt_regs area */ - /* data is the 4 bytes that the user wants written */ - /* addr is the offset into the other process' pt_regs structure that is to be written into */ - /* (this is run in a 32-bit process looking at a 64-bit process) */ - case PPC_PTRACE_POKEUSR_3264: - { + /* + * Write 4 bytes into the other process' pt_regs area + * data is the 4 bytes that the user wants written + * addr is the offset into the other process' pt_regs structure + * that is to be written into + * (this is run in a 32-bit process looking at a 64-bit process) + */ + case PPC_PTRACE_POKEUSR_3264: { u32 index; u32 numReg; ret = -EIO; - /* Determine which register the user wants */ - index = (u64)addr >> 2; /* Divide addr by 4 */ + index = (u64)addr >> 2; numReg = index / 2; - - /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ - if ((addr & 3) || numReg > PT_FPSCR) + /* + * Validate the input - check to see if address is on the + * wrong boundary or beyond the end of the user area + */ + if ((addr & 3) || (numReg > PT_FPSCR)) break; /* Insure it is a register we let them change */ - if ((numReg == PT_ORIG_R3) || ((numReg > PT_CCR) && (numReg < PT_FPR0))) + if ((numReg == PT_ORIG_R3) + || ((numReg > PT_CCR) && (numReg < PT_FPR0))) break; - - if (numReg >= PT_FPR0) - { + if (numReg >= PT_FPR0) { if (child->thread.regs->msr & MSR_FP) giveup_fpu(child); } - if (numReg == PT_MSR) - data = (data & MSR_DEBUGCHANGE) | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); - + data = (data & MSR_DEBUGCHANGE) + | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); ((u32*)child->thread.regs)[index] = data; ret = 0; break; @@ -351,8 +311,8 @@ } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/rtas-proc.c Wed Jul 24 14:03:38 2002 @@ -162,26 +162,26 @@ size_t count, loff_t *ppos); struct file_operations ppc_rtas_poweron_operations = { - read: ppc_rtas_poweron_read, - write: ppc_rtas_poweron_write + .read = ppc_rtas_poweron_read, + .write = ppc_rtas_poweron_write }; struct file_operations ppc_rtas_progress_operations = { - read: ppc_rtas_progress_read, - write: ppc_rtas_progress_write + .read = ppc_rtas_progress_read, + .write = ppc_rtas_progress_write }; struct file_operations ppc_rtas_clock_operations = { - read: ppc_rtas_clock_read, - write: ppc_rtas_clock_write + .read = ppc_rtas_clock_read, + .write = ppc_rtas_clock_write }; struct file_operations ppc_rtas_tone_freq_operations = { - read: ppc_rtas_tone_freq_read, - write: ppc_rtas_tone_freq_write + .read = ppc_rtas_tone_freq_read, + .write = ppc_rtas_tone_freq_write }; struct file_operations ppc_rtas_tone_volume_operations = { - read: ppc_rtas_tone_volume_read, - write: ppc_rtas_tone_volume_write + .read = ppc_rtas_tone_volume_read, + .write = ppc_rtas_tone_volume_write }; int ppc_rtas_find_all_sensors (void); diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/kernel/rtas.c Wed Jul 24 14:03:36 2002 @@ -16,15 +16,19 @@ #include #include -#include #include #include +#include #include #include #include #include +#include #include +struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */ +struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; + /* * prom_init() is called very early on, before the kernel text * and data have been mapped to KERNELBASE. At this point the code @@ -47,7 +51,7 @@ */ struct rtas_t rtas = { - lock: SPIN_LOCK_UNLOCKED + .lock = SPIN_LOCK_UNLOCKED }; extern unsigned long reloc_offset(void); @@ -105,7 +109,6 @@ #if 0 #define DEBUG_RTAS #endif -__openfirmware int rtas_token(const char *service) { @@ -120,7 +123,6 @@ return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } -__openfirmware long rtas_call(int token, int nargs, int nret, unsigned long *outputs, ...) @@ -184,25 +186,107 @@ return (ulong)((nret > 0) ? rtas_args->rets[0] : 0); } -void __chrp +#define FLASH_BLOCK_LIST_VERSION (1UL) +static void +rtas_flash_firmware(void) +{ + unsigned long image_size; + struct flash_block_list *f, *next, *flist; + unsigned long rtas_block_list; + int i, status, update_token; + + update_token = rtas_token("ibm,update-flash-64-and-reboot"); + if (update_token == RTAS_UNKNOWN_SERVICE) { + printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); + printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); + return; + } + + /* NOTE: the "first" block list is a global var with no data + * blocks in the kernel data segment. We do this because + * we want to ensure this block_list addr is under 4GB. + */ + rtas_firmware_flash_list.num_blocks = 0; + flist = (struct flash_block_list *)&rtas_firmware_flash_list; + rtas_block_list = virt_to_absolute((unsigned long)flist); + if (rtas_block_list >= (4UL << 20)) { + printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); + return; + } + + printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); + /* Update the block_list in place. */ + image_size = 0; + for (f = flist; f; f = next) { + /* Translate data addrs to absolute */ + for (i = 0; i < f->num_blocks; i++) { + f->blocks[i].data = (char *)virt_to_absolute((unsigned long)f->blocks[i].data); + image_size += f->blocks[i].length; + } + next = f->next; + f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + /* make num_blocks into the version/length field */ + f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); + } + + printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); + printk(KERN_ALERT "FLASH: performing flash and reboot\n"); + ppc_md.progress("Flashing \n", 0x0); + ppc_md.progress("Please Wait... ", 0x0); + printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); + status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); + switch (status) { /* should only get "bad" status */ + case 0: + printk(KERN_ALERT "FLASH: success\n"); + break; + case -1: + printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); + break; + case -3: + printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); + break; + case -4: + printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); + break; + default: + printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); + break; + } +} + +void rtas_flash_bypass_warning(void) +{ + printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); + printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); +} + + +void rtas_restart(char *cmd) { + if (rtas_firmware_flash_list.next) + rtas_flash_firmware(); + printk("RTAS system-reboot returned %ld\n", rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); for (;;); } -void __chrp +void rtas_power_off(void) { + if (rtas_firmware_flash_list.next) + rtas_flash_bypass_warning(); /* allow power on only with power button press */ printk("RTAS power-off returned %ld\n", rtas_call(rtas_token("power-off"), 2, 1, NULL,0xffffffff,0xffffffff)); for (;;); } -void __chrp +void rtas_halt(void) { + if (rtas_firmware_flash_list.next) + rtas_flash_bypass_warning(); rtas_power_off(); } diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/rtas_flash.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,240 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * 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. + * + * /proc/ppc64/rtas/firmware_flash interface + * + * This file implements a firmware_flash interface to pump a firmware + * image into the kernel. At reboot time rtas_restart() will see the + * firmware image and flash it as it reboots (see rtas.c). + */ + +#include + +#include +#include +#include +#include +#include + +#define MODULE_VERSION "1.0" +#define MODULE_NAME "rtas_flash" + +#define FIRMWARE_FLASH_NAME "firmware_flash" + +/* Local copy of the flash block list. + * We only allow one open of the flash proc file and create this + * list as we go. This list will be put in the kernel's + * rtas_firmware_flash_list global var once it is fully read. + * + * For convenience as we build the list we use virtual addrs, + * we do not fill in the version number, and the length field + * is treated as the number of entries currently in the block + * (i.e. not a byte count). This is all fixed on release. + */ +static struct flash_block_list *flist; +static char *flash_msg; +static int flash_possible; + +static int rtas_flash_open(struct inode *inode, struct file *file) +{ + if ((file->f_mode & FMODE_WRITE) && flash_possible) { + if (flist) + return -EBUSY; + flist = (struct flash_block_list *)get_free_page(GFP_KERNEL); + if (!flist) + return -ENOMEM; + } + return 0; +} + +/* Do simple sanity checks on the flash image. */ +static int flash_list_valid(struct flash_block_list *flist) +{ + struct flash_block_list *f; + int i; + unsigned long block_size, image_size; + + flash_msg = NULL; + /* Paranoid self test here. We also collect the image size. */ + image_size = 0; + for (f = flist; f; f = f->next) { + for (i = 0; i < f->num_blocks; i++) { + if (f->blocks[i].data == NULL) { + flash_msg = "error: internal error null data\n"; + return 0; + } + block_size = f->blocks[i].length; + if (block_size <= 0 || block_size > PAGE_SIZE) { + flash_msg = "error: internal error bad length\n"; + return 0; + } + image_size += block_size; + } + } + if (image_size < (256 << 10)) { + if (image_size < 2) + flash_msg = NULL; /* allow "clear" of image */ + else + flash_msg = "error: flash image short\n"; + return 0; + } + printk(KERN_INFO "FLASH: flash image with %ld bytes stored for hardware flash on reboot\n", image_size); + return 1; +} + +static void free_flash_list(struct flash_block_list *f) +{ + struct flash_block_list *next; + int i; + + while (f) { + for (i = 0; i < f->num_blocks; i++) + free_page((unsigned long)(f->blocks[i].data)); + next = f->next; + free_page((unsigned long)f); + f = next; + } +} + +static int rtas_flash_release(struct inode *inode, struct file *file) +{ + if (flist) { + /* Always clear saved list on a new attempt. */ + if (rtas_firmware_flash_list.next) { + free_flash_list(rtas_firmware_flash_list.next); + rtas_firmware_flash_list.next = NULL; + } + + if (flash_list_valid(flist)) + rtas_firmware_flash_list.next = flist; + else + free_flash_list(flist); + flist = NULL; + } + return 0; +} + +/* Reading the proc file will show status (not the firmware contents) */ +static ssize_t rtas_flash_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + int error; + char *msg; + int msglen; + + if (!flash_possible) { + msg = "error: this partition does not have service authority\n"; + } else if (flist) { + msg = "info: this file is busy for write by some process\n"; + } else if (flash_msg) { + msg = flash_msg; /* message from last flash attempt */ + } else if (rtas_firmware_flash_list.next) { + msg = "ready: firmware image ready for flash on reboot\n"; + } else { + msg = "info: no firmware image for flash\n"; + } + msglen = strlen(msg); + if (msglen > count) + msglen = count; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + error = verify_area(VERIFY_WRITE, buf, msglen); + if (error) + return -EINVAL; + + copy_to_user(buf, msg, msglen); + + if (ppos) + *ppos = msglen; + return msglen; +} + +/* We could be much more efficient here. But to keep this function + * simple we allocate a page to the block list no matter how small the + * count is. If the system is low on memory it will be just as well + * that we fail.... + */ +static ssize_t rtas_flash_write(struct file *file, const char *buffer, + size_t count, loff_t *off) +{ + size_t len = count; + char *p; + int next_free; + struct flash_block_list *fl = flist; + + if (!flash_possible || len == 0) + return len; /* discard data */ + + while (fl->next) + fl = fl->next; /* seek to last block_list for append */ + next_free = fl->num_blocks; + if (next_free == FLASH_BLOCKS_PER_NODE) { + /* Need to allocate another block_list */ + fl->next = (struct flash_block_list *)get_free_page(GFP_KERNEL); + if (!fl->next) + return -ENOMEM; + fl = fl->next; + next_free = 0; + } + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + p = (char *)get_free_page(GFP_KERNEL); + if (!p) + return -ENOMEM; + if(copy_from_user(p, buffer, len)) { + free_page((unsigned long)p); + return -EFAULT; + } + fl->blocks[next_free].data = p; + fl->blocks[next_free].length = len; + fl->num_blocks++; + + return len; +} + +static struct file_operations rtas_flash_operations = { + read: rtas_flash_read, + write: rtas_flash_write, + open: rtas_flash_open, + release: rtas_flash_release, +}; + + +int __init rtas_flash_init(void) +{ + struct proc_dir_entry *ent = NULL; + + if (!rtas_proc_dir) { + printk(KERN_WARNING "rtas proc dir does not already exist"); + return -ENOENT; + } + + if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) + flash_possible = 1; + + if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) { + ent->nlink = 1; + ent->proc_fops = &rtas_flash_operations; + ent->owner = THIS_MODULE; + } + return 0; +} + +void __exit rtas_flash_cleanup(void) +{ + if (!rtas_proc_dir) + return; + remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir); +} + +module_init(rtas_flash_init); +module_exit(rtas_flash_cleanup); +MODULE_LICENSE("GPL"); diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c --- a/arch/ppc64/kernel/rtasd.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/kernel/rtasd.c Wed Jul 24 14:03:37 2002 @@ -114,10 +114,10 @@ } struct file_operations proc_rtas_log_operations = { - read: rtas_log_read, - poll: rtas_log_poll, - open: rtas_log_open, - release: rtas_log_release, + .read = rtas_log_read, + .poll = rtas_log_poll, + .open = rtas_log_open, + .release = rtas_log_release, }; static void log_rtas(char *buf) @@ -220,10 +220,15 @@ current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1; #endif - cpu = 0; - set_cpus_allowed(current, 1UL << cpu_logical_map(cpu)); +repeat: + for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (!cpu_online(cpu)) + continue; + + DEBUG("scheduling on %d\n", cpu); + set_cpus_allowed(current, 1UL << cpu); + DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id()); - while(1) { do { memset(logdata, 0, rtas_error_log_max); error = rtas_call(event_scan, 4, 1, NULL, @@ -239,31 +244,23 @@ } while(error == 0); - DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id()); - - cpu++; - if (cpu >= smp_num_cpus) { - - if (first_pass && surveillance_requested) { - DEBUG("enabling surveillance\n"); - if (enable_surveillance()) - goto error_vfree; - DEBUG("surveillance enabled\n"); - } - - first_pass = 0; - cpu = 0; - } - - set_cpus_allowed(current, 1UL << cpu_logical_map(cpu)); - - /* Check all cpus for pending events before sleeping*/ if (!first_pass) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((HZ*60/rtas_event_scan_rate) / 2); } } + + if (first_pass && surveillance_requested) { + DEBUG("enabling surveillance\n"); + if (enable_surveillance()) + goto error_vfree; + DEBUG("surveillance enabled\n"); + } else { + first_pass = 0; + } + + goto repeat; error_vfree: vfree(rtas_log_buf); diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c --- a/arch/ppc64/kernel/rtc.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/rtc.c Wed Jul 24 14:03:38 2002 @@ -178,12 +178,12 @@ * The various file operations we support. */ static struct file_operations rtc_fops = { - owner: THIS_MODULE, - llseek: rtc_llseek, - read: rtc_read, - ioctl: rtc_ioctl, - open: rtc_open, - release: rtc_release, + .owner = THIS_MODULE, + .llseek = rtc_llseek, + .read = rtc_read, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, }; static struct miscdevice rtc_dev= diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/setup.c Wed Jul 24 14:03:38 2002 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -43,9 +42,6 @@ extern HTAB htab_data; extern unsigned long loops_per_jiffy; -extern unsigned long embedded_sysmap_start; -extern unsigned long embedded_sysmap_end; - int have_of = 1; extern void chrp_init(unsigned long r3, @@ -54,7 +50,6 @@ unsigned long r6, unsigned long r7); -extern void chrp_init_map_io_space( void ); extern void iSeries_init( void ); extern void iSeries_init_early( void ); extern void pSeries_init_early( void ); @@ -173,10 +168,6 @@ udbg_puthex((unsigned long)naca); udbg_putc('\n'); - udbg_puts("naca->processorCount = 0x"); - udbg_puthex(naca->processorCount); - udbg_putc('\n'); - udbg_puts("naca->physicalMemorySize = 0x"); udbg_puthex(naca->physicalMemorySize); udbg_putc('\n'); @@ -294,6 +285,9 @@ pvr = paca[cpu_id].pvr; switch (PVR_VER(pvr)) { + case PV_NORTHSTAR: + seq_printf(m, "RS64-II (northstar)\n"); + break; case PV_PULSAR: seq_printf(m, "RS64-III (pulsar)\n"); break; @@ -306,6 +300,9 @@ case PV_SSTAR: seq_printf(m, "RS64-IV (sstar)\n"); break; + case PV_POWER4p: + seq_printf(m, "POWER4+ (gq)\n"); + break; case PV_630: seq_printf(m, "POWER3 (630)\n"); break; @@ -338,7 +335,7 @@ if (ppc_md.setup_residual != NULL) ppc_md.setup_residual(m, cpu_id); - seq_printf(m, "revision\t: %hd.%hd\n", maj, min); + seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min); return 0; } @@ -356,10 +353,10 @@ { } struct seq_operations cpuinfo_op = { - start: c_start, - next: c_next, - stop: c_stop, - show: show_cpuinfo, + .start =c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, }; /* @@ -499,6 +496,7 @@ } extern void (*calibrate_delay)(void); +extern void sort_exception_table(void); /* * Called into from start_kernel, after lock_kernel has been called. diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc64/kernel/signal.c Wed Jul 24 14:03:35 2002 @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -59,9 +57,36 @@ */ #define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) -int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern long sys_wait4(pid_t pid, unsigned int *stat_addr, - int options, /*unsigned long*/ struct rusage *ru); +/* + * When we have signals to deliver, we set up on the + * user stack, going down from the original stack pointer: + * a sigregs struct + * one or more sigcontext structs with + * a gap of __SIGNAL_FRAMESIZE bytes + * + * Each of these things must be a multiple of 16 bytes in size. + * + */ +struct sigregs { + elf_gregset_t gp_regs; + double fp_regs[ELF_NFPREG]; + unsigned int tramp[2]; + /* 64 bit API allows for 288 bytes below sp before + decrementing it. */ + int abigap[72]; +}; + +struct rt_sigframe +{ + unsigned long _unused[2]; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; +}; + + +extern int do_signal(sigset_t *oldset, struct pt_regs *regs); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -127,7 +152,7 @@ long sys_sigaltstack(const stack_t *uss, stack_t *uoss) { - struct pt_regs *regs = (struct pt_regs *) &uss; + struct pt_regs *regs = (struct pt_regs *)&uss; return do_sigaltstack(uss, uoss, regs->gpr[1]); } @@ -139,6 +164,7 @@ if (act) { old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) @@ -148,8 +174,7 @@ siginitset(&new_ka.sa.sa_mask, mask); } - ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL)); - + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || @@ -163,35 +188,6 @@ } /* - * When we have signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one or more sigcontext structs with - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * - */ -struct sigregs { - elf_gregset_t gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned int tramp[2]; - /* 64 bit API allows for 288 bytes below sp before - decrementing it. */ - int abigap[72]; -}; - -struct rt_sigframe -{ - unsigned long _unused[2]; - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; -}; - - -/* * When we have rt signals to deliver, we set up on the * user stack, going down from the original stack pointer: * a sigregs struct @@ -231,7 +227,7 @@ * preamble frame (where registers are stored) * see handle_signal() */ - sr = (struct sigregs *) sigctx.regs; + sr = (struct sigregs *)sigctx.regs; if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) goto badframe; saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) @@ -251,11 +247,10 @@ do_exit(SIGSEGV); } -static void -setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, +static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, signed long newsp) { - struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp; + struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second @@ -277,11 +272,13 @@ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) || __copy_to_user(&frame->fp_regs, current->thread.fpr, ELF_NFPREG * sizeof(double)) - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) /* li r0, __NR_rt_sigreturn */ - || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ + /* li r0, __NR_rt_sigreturn */ + || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) + /* sc */ + || __put_user(0x44000002UL, &frame->tramp[1])) goto badframe; - flush_icache_range((unsigned long) &frame->tramp[0], - (unsigned long) &frame->tramp[2]); + flush_icache_range((unsigned long)&frame->tramp[0], + (unsigned long)&frame->tramp[2]); current->thread.fpscr = 0; /* turn off all fp exceptions */ /* Retrieve rt_sigframe from stack and @@ -289,11 +286,11 @@ */ newsp -= __SIGNAL_FRAMESIZE; - if ( get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { + if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { goto badframe; } - funct_desc_ptr = ( struct funct_descr_entry *) temp_ptr; + funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; if (put_user(regs->gpr[1], (unsigned long *)newsp) || get_user(regs->nip, &funct_desc_ptr->entry) @@ -304,8 +301,8 @@ goto badframe; regs->gpr[1] = newsp; - regs->gpr[6] = (unsigned long) rt_sf; - regs->link = (unsigned long) frame->tramp; + regs->gpr[6] = (unsigned long)rt_sf; + regs->link = (unsigned long)frame->tramp; return; @@ -342,11 +339,11 @@ current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); - if (regs->msr & MSR_FP ) + if (regs->msr & MSR_FP) giveup_fpu(current); /* restore registers */ - sr = (struct sigregs *) sigctx.regs; + sr = (struct sigregs *)sigctx.regs; if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) goto badframe; saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) @@ -367,8 +364,7 @@ /* * Set up a signal frame. */ -static void -setup_frame(struct pt_regs *regs, struct sigregs *frame, +static void setup_frame(struct pt_regs *regs, struct sigregs *frame, unsigned long newsp) { @@ -385,7 +381,7 @@ struct funct_descr_entry * funct_desc_ptr; unsigned long temp_ptr; - struct sigcontext_struct *sc = (struct sigcontext_struct *) newsp; + struct sigcontext_struct *sc = (struct sigcontext_struct *)newsp; if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; @@ -394,27 +390,29 @@ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) || __copy_to_user(&frame->fp_regs, current->thread.fpr, ELF_NFPREG * sizeof(double)) - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) /* li r0, __NR_sigreturn */ - || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ + /* li r0, __NR_sigreturn */ + || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) + /* sc */ + || __put_user(0x44000002UL, &frame->tramp[1])) goto badframe; - flush_icache_range((unsigned long) &frame->tramp[0], - (unsigned long) &frame->tramp[2]); + flush_icache_range((unsigned long)&frame->tramp[0], + (unsigned long)&frame->tramp[2]); current->thread.fpscr = 0; /* turn off all fp exceptions */ newsp -= __SIGNAL_FRAMESIZE; - if ( get_user(temp_ptr, &sc->handler)) + if (get_user(temp_ptr, &sc->handler)) goto badframe; - funct_desc_ptr = ( struct funct_descr_entry *) temp_ptr; + funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, & funct_desc_ptr ->entry) - || get_user(regs->gpr[2],& funct_desc_ptr->toc) + || get_user(regs->nip, &funct_desc_ptr ->entry) + || get_user(regs->gpr[2],&funct_desc_ptr->toc) || get_user(regs->gpr[3], &sc->signal)) goto badframe; regs->gpr[1] = newsp; - regs->gpr[4] = (unsigned long) sc; - regs->link = (unsigned long) frame->tramp; + regs->gpr[4] = (unsigned long)sc; + regs->link = (unsigned long)frame->tramp; return; @@ -429,8 +427,7 @@ /* * OK, we're invoking a handler */ -static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, +static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, unsigned long *newspp, unsigned long frame) { struct sigcontext_struct *sc; @@ -447,11 +444,12 @@ if (ka->sa.sa_flags & SA_SIGINFO) { /* Put a Real Time Context onto stack */ *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe *) *newspp; + rt_sf = (struct rt_sigframe *)*newspp; if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) goto badframe; - if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler) + if (__put_user((unsigned long)ka->sa.sa_handler, + &rt_sf->uc.uc_mcontext.handler) || __put_user(&rt_sf->info, &rt_sf->pinfo) || __put_user(&rt_sf->uc, &rt_sf->puc) /* Put the siginfo */ @@ -461,9 +459,11 @@ || __put_user(0, &rt_sf->uc.uc_link) || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)) + &rt_sf->uc.uc_stack.ss_flags) + || __put_user(current->sas_ss_size, + &rt_sf->uc.uc_stack.ss_size) + || __copy_to_user(&rt_sf->uc.uc_sigmask, + oldset, sizeof(*oldset)) /* mcontext.regs points to preamble register frame */ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) @@ -471,11 +471,11 @@ } else { /* Put a sigcontext on the stack */ *newspp -= sizeof(*sc); - sc = (struct sigcontext_struct *) *newspp; + sc = (struct sigcontext_struct *)*newspp; if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) goto badframe; - if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) + if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler) || __put_user(oldset->sig[0], &sc->oldmask) #if _NSIG_WORDS > 1 || __put_user(oldset->sig[1], &sc->_unused[3]) @@ -512,6 +512,7 @@ * mistake. */ extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); + int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; @@ -526,7 +527,7 @@ if (test_thread_flag(TIF_32BIT)) return do_signal32(oldset, regs); - if (!oldset) + if (!oldset) oldset = ¤t->blocked; newsp = frame = 0; @@ -534,8 +535,8 @@ signr = get_signal_to_deliver(&info, regs); if (signr > 0) { ka = ¤t->sig->action[signr-1]; - if ( (ka->sa.sa_flags & SA_ONSTACK) - && (! on_sig_stack(regs->gpr[1]))) + if ((ka->sa.sa_flags & SA_ONSTACK) + && (!on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); else newsp = regs->gpr[1]; @@ -557,9 +558,10 @@ if (newsp == frame) return 0; /* no signals delivered */ + /* Invoke correct stack setup routine */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *) frame, newsp); + setup_rt_frame(regs, (struct sigregs *)frame, newsp); else - setup_frame(regs, (struct sigregs *) frame, newsp); + setup_frame(regs, (struct sigregs *)frame, newsp); return 1; } diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/signal32.c Wed Jul 24 14:03:39 2002 @@ -14,43 +14,19 @@ * 2 of the License, or (at your option) any later version. */ -#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 #include +#include #include #include +#include #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) /* @@ -112,9 +88,6 @@ }; -extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, - int options, struct rusage * ru); - /* * Start of nonRT signal support @@ -133,7 +106,7 @@ * setup_frame32 */ -asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, +long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { struct k_sigaction new_ka, old_ka; @@ -145,32 +118,30 @@ if (act) { old_sigset_t32 mask; - ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); - ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer); - ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - ret |= __get_user(mask, &act->sa_mask); - if (ret) - return ret; + if (get_user((long)new_ka.sa.sa_handler, &act->sa_handler) || + __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) + return -EFAULT; siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); - ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); - ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + if (put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) + return -EFAULT; } return ret; } +extern long sys_sigpending(old_sigset_t *set); - -extern asmlinkage long sys_sigpending(old_sigset_t *set); - -asmlinkage long sys32_sigpending(old_sigset_t32 *set) +long sys32_sigpending(old_sigset_t32 *set) { old_sigset_t s; int ret; @@ -185,9 +156,7 @@ } - - -extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, +extern long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset); /* @@ -197,7 +166,7 @@ * 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 long sys32_sigprocmask(u32 how, old_sigset_t32 *set, +long sys32_sigprocmask(u32 how, old_sigset_t32 *set, old_sigset_t32 *oset) { old_sigset_t s; @@ -252,23 +221,21 @@ * Note that PPC32 puts the upper 32 bits of the sigmask in the * unused part of the signal stackframe */ - set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3])<< 32); + set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32); sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); - - /* Last stacked signal - restore registers */ - sr = (struct sigregs32*)(u64)sigctx.regs; if (regs->msr & MSR_FP ) giveup_fpu(current); + /* Last stacked signal - restore registers */ + sr = (struct sigregs32*)(u64)sigctx.regs; /* * copy the 32 bit register values off the user stack * into the 32 bit register area */ - if (copy_from_user(saved_regs, &sr->gp_regs, - sizeof(sr->gp_regs))) + if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) goto badframe; /* * The saved reg structure in the frame is an elf_grepset_t32, @@ -323,7 +290,6 @@ goto badframe; ret = regs->result; - return ret; badframe: @@ -387,12 +353,13 @@ */ if (__copy_to_user(&frame->fp_regs, current->thread.fpr, ELF_NFPREG * sizeof(double)) - || __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0]) /* li r0, __NR_sigreturn */ - || __put_user(0x44000002U, &frame->tramp[1])) /* sc */ + /* li r0, __NR_sigreturn */ + || __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0]) + /* sc */ + || __put_user(0x44000002U, &frame->tramp[1])) goto badframe; - - flush_icache_range((unsigned long) &frame->tramp[0], - (unsigned long) &frame->tramp[2]); + flush_icache_range((unsigned long)&frame->tramp[0], + (unsigned long)&frame->tramp[2]); current->thread.fpscr = 0; /* turn off all fp exceptions */ newsp -= __SIGNAL_FRAMESIZE32; @@ -438,7 +405,7 @@ * * Other routines * setup_rt_frame32 - * siginfo64to32 + * copy_siginfo_to_user32 * siginfo32to64 */ @@ -451,50 +418,45 @@ unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs * regs) { - struct rt_sigframe_32 *rt_stack_frame; + struct rt_sigframe_32 *rt_sf; struct sigcontext32_struct sigctx; - struct sigregs32 *signalregs; + struct sigregs32 *sr; int ret; elf_gregset_t32 saved_regs; /* an array of 32 bit register values */ - sigset_t signal_set; - stack_t stack; + sigset_t set; + stack_t st; int i; - ret = 0; /* Adjust the inputted reg1 to point to the first rt signal frame */ - rt_stack_frame = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); + rt_sf = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); /* Copy the information from the user stack */ - if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext, - sizeof(sigctx)) - || copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask, - sizeof(signal_set)) - || copy_from_user(&stack,&rt_stack_frame->uc.uc_stack, - sizeof(stack))) + if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) + || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) + || copy_from_user(&st,&rt_sf->uc.uc_stack, sizeof(st))) goto badframe; /* * Unblock the signal that was processed * After a signal handler runs - * if the signal is blockable - the signal will be unblocked - * ( sigkill and sigstop are not blockable) + * (sigkill and sigstop are not blockable) */ - sigdelsetmask(&signal_set, ~_BLOCKABLE); + sigdelsetmask(&set, ~_BLOCKABLE); /* update the current based on the sigmask found in the rt_stackframe */ spin_lock_irq(¤t->sigmask_lock); - current->blocked = signal_set; + current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); + /* If currently owning the floating point - give them up */ + if (regs->msr & MSR_FP) + giveup_fpu(current); /* * Set to point to the next rt_sigframe - this is used to * determine whether this is the last signal to process */ - signalregs = (struct sigregs32 *) (u64)sigctx.regs; - /* If currently owning the floating point - give them up */ - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (copy_from_user(saved_regs, &signalregs->gp_regs, - sizeof(signalregs->gp_regs))) + sr = (struct sigregs32 *)(u64)sigctx.regs; + if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) goto badframe; /* * The saved reg structure in the frame is an elf_grepset_t32, @@ -544,7 +506,7 @@ -asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, +long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, size_t sigsetsize) { struct k_sigaction new_ka, old_ka; @@ -599,7 +561,7 @@ } -extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, +extern long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); /* @@ -609,7 +571,7 @@ * 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 long sys32_rt_sigprocmask(u32 how, sigset32_t *set, +long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset, size_t sigsetsize) { sigset_t s; @@ -649,10 +611,10 @@ } -extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); +extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); -asmlinkage long sys32_rt_sigpending(sigset32_t *set, +long sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsetsize) { sigset_t s; @@ -677,50 +639,54 @@ } -siginfo_t32 *siginfo64to32(siginfo_t32 *d, siginfo_t *s) +static int copy_siginfo_to_user32(siginfo_t32 *d, siginfo_t *s) { - memset (d, 0, sizeof(siginfo_t32)); - d->si_signo = s->si_signo; - d->si_errno = s->si_errno; - /* XXX why dont we just implement copy_siginfo_to_user32? - Anton */ - d->si_code = s->si_code & 0xffff; + int err; + + if (!access_ok (VERIFY_WRITE, d, sizeof(*d))) + return -EFAULT; + + err = __put_user(s->si_signo, &d->si_signo); + err |= __put_user(s->si_errno, &d->si_errno); + err |= __put_user((short)s->si_code, &d->si_code); if (s->si_signo >= SIGRTMIN) { - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; - d->si_int = s->si_int; + err |= __put_user(s->si_pid, &d->si_pid); + err |= __put_user(s->si_uid, &d->si_uid); + err |= __put_user(s->si_int, &d->si_int); } else { switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: - d->si_pid = s->si_pid; - d->si_status = s->si_status; - d->si_utime = s->si_utime; - d->si_stime = s->si_stime; + err |= __put_user(s->si_pid, &d->si_pid); + err |= __put_user(s->si_status, &d->si_status); + err |= __put_user(s->si_utime, &d->si_utime); + err |= __put_user(s->si_stime, &d->si_stime); break; case SIGSEGV: case SIGBUS: case SIGFPE: case SIGILL: - d->si_addr = (long)(s->si_addr); + err |= __put_user((long)(s->si_addr), &d->si_addr); break; case SIGPOLL: - d->si_band = s->si_band; - d->si_fd = s->si_fd; + err |= __put_user(s->si_band, &d->si_band); + err |= __put_user(s->si_fd, &d->si_fd); break; default: - d->si_pid = s->si_pid; - d->si_uid = s->si_uid; + err |= __put_user(s->si_pid, &d->si_pid); + err |= __put_user(s->si_uid, &d->si_uid); break; } } - return d; + return err; } -extern asmlinkage long sys_rt_sigtimedwait(const sigset_t *uthese, + +extern long sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize); -asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, +long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts, __kernel_size_t32 sigsetsize) { sigset_t s; @@ -729,8 +695,7 @@ int ret; mm_segment_t old_fs = get_fs(); siginfo_t info; - siginfo_t32 info32; - + if (copy_from_user(&s32, uthese, sizeof(sigset32_t))) return -EFAULT; switch (_NSIG_WORDS) { @@ -753,8 +718,7 @@ sigsetsize); set_fs(old_fs); if (ret >= 0 && uinfo) { - if (copy_to_user (uinfo, siginfo64to32(&info32, &info), - sizeof(siginfo_t32))) + if (copy_siginfo_to_user32(uinfo, &info)) return -EFAULT; } return ret; @@ -762,7 +726,7 @@ -siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) +static siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) { d->si_signo = s->si_signo; d->si_errno = s->si_errno; @@ -800,7 +764,7 @@ } -extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); +extern long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); /* * Note: it is necessary to treat pid and sig as unsigned ints, with the @@ -809,7 +773,7 @@ * (msr in 32-bit mode) and the register representation of a signed int * (msr in 64-bit mode) is performed. */ -asmlinkage long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) +long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) { siginfo_t info; siginfo_t32 info32; @@ -974,8 +938,7 @@ unsigned int frame) { struct sigcontext32_struct *sc; - struct rt_sigframe_32 *rt_stack_frame; - siginfo_t32 siginfo32bit; + struct rt_sigframe_32 *rt_sf; struct k_sigaction *ka = ¤t->sig->action[sig-1]; if (regs->trap == 0x0C00 /* System Call! */ @@ -986,42 +949,35 @@ /* * Set up the signal frame - * Determine if an real time frame - siginfo required + * Determine if a real time frame and a siginfo is required */ if (ka->sa.sa_flags & SA_SIGINFO) { - siginfo64to32(&siginfo32bit,info); - *newspp -= sizeof(*rt_stack_frame); - rt_stack_frame = (struct rt_sigframe_32 *)(u64)(*newspp); - - if (verify_area(VERIFY_WRITE, rt_stack_frame, - sizeof(*rt_stack_frame))) + *newspp -= sizeof(*rt_sf); + rt_sf = (struct rt_sigframe_32 *)(u64)(*newspp); + if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) goto badframe; if (__put_user((u32)(u64)ka->sa.sa_handler, - &rt_stack_frame->uc.uc_mcontext.handler) - || __put_user((u32)(u64)&rt_stack_frame->info, - &rt_stack_frame->pinfo) - || __put_user((u32)(u64)&rt_stack_frame->uc, - &rt_stack_frame->puc) + &rt_sf->uc.uc_mcontext.handler) + || __put_user((u32)(u64)&rt_sf->info, &rt_sf->pinfo) + || __put_user((u32)(u64)&rt_sf->uc, &rt_sf->puc) /* put the siginfo on the user stack */ - || __copy_to_user(&rt_stack_frame->info, &siginfo32bit, - sizeof(siginfo32bit)) + || copy_siginfo_to_user32(&rt_sf->info, info) /* set the ucontext on the user stack */ - || __put_user(0, &rt_stack_frame->uc.uc_flags) - || __put_user(0, &rt_stack_frame->uc.uc_link) - || __put_user(current->sas_ss_sp, - &rt_stack_frame->uc.uc_stack.ss_sp) + || __put_user(0, &rt_sf->uc.uc_flags) + || __put_user(0, &rt_sf->uc.uc_link) + || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_stack_frame->uc.uc_stack.ss_flags) + &rt_sf->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, - &rt_stack_frame->uc.uc_stack.ss_size) - || __copy_to_user(&rt_stack_frame->uc.uc_sigmask, + &rt_sf->uc.uc_stack.ss_size) + || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)) /* point the mcontext.regs to the pramble register frame */ - || __put_user(frame, &rt_stack_frame->uc.uc_mcontext.regs) - || __put_user(sig,&rt_stack_frame->uc.uc_mcontext.signal)) + || __put_user(frame, &rt_sf->uc.uc_mcontext.regs) + || __put_user(sig,&rt_sf->uc.uc_mcontext.signal)) goto badframe; } else { - /* Put another sigcontext on the stack */ + /* Put a sigcontext on the stack */ *newspp -= sizeof(*sc); sc = (struct sigcontext32_struct *)(u64)*newspp; if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) @@ -1048,7 +1004,6 @@ recalc_sigpending(); spin_unlock_irq(¤t->sigmask_lock); } - return; badframe: @@ -1068,7 +1023,7 @@ * sigaltatck sys32_sigaltstack */ -asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, +int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int p4, int p6, int p7, struct pt_regs *regs) { stack_t uss, uoss; @@ -1114,7 +1069,7 @@ /* * Start of do_signal32 routine * - * This routine gets control when a pemding signal needs to be processed + * This routine gets control when a pending signal needs to be processed * in the 32 bit target thread - * * It handles both rt and non-rt signals @@ -1141,13 +1096,13 @@ signr = get_signal_to_deliver(&info, regs); if (signr > 0) { ka = ¤t->sig->action[signr-1]; - - if ((ka->sa.sa_flags & SA_ONSTACK) && - (!on_sig_stack(regs->gpr[1]))) + if ((ka->sa.sa_flags & SA_ONSTACK) + && (!on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); else newsp = regs->gpr[1]; newsp = frame = newsp - sizeof(struct sigregs32); + /* Whee! Actually deliver the signal. */ handle_signal32(signr, &info, oldset, regs, &newsp, frame); } @@ -1165,10 +1120,9 @@ return 0; /* no signals delivered */ /* Invoke correct stack setup routine */ - if (ka->sa.sa_flags & SA_SIGINFO) + if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); else setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp); - return 1; } diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/smp.c Wed Jul 24 14:03:39 2002 @@ -28,7 +28,6 @@ #define __KERNEL_SYSCALLS__ #include #include -/* #include */ #include #include #include @@ -40,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -56,20 +54,18 @@ int smp_threads_ready = 0; volatile int smp_commenced = 0; -int smp_num_cpus = 1; int smp_tb_synchronized = 0; spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED; unsigned long cache_decay_ticks; static int max_cpus __initdata = NR_CPUS; -unsigned long cpu_online_map; +/* initialised so it doesnt end up in bss */ +unsigned long cpu_online_map = 0; +int boot_cpuid = 0; +int ppc64_is_smp = 0; volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; -#define TB_SYNC_PASSES 4 -volatile unsigned long __initdata tb_sync_flag = 0; -volatile unsigned long __initdata tb_offset = 0; - extern unsigned char stab_array[]; int start_secondary(void *); @@ -104,7 +100,7 @@ int cpu = smp_processor_id(); int msg; - if ( smp_num_cpus < 2 ) + if ( num_online_cpus() < 2 ) return; for ( msg = 0; msg < 4; ++msg ) @@ -116,11 +112,16 @@ static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait) { int i; - for (i = 0; i < smp_num_cpus; ++i) { - if ( (target == MSG_ALL) || - (target == i) || - ((target == MSG_ALL_BUT_SELF) && (i != smp_processor_id())) ) { - set_bit( msg, &iSeries_smp_message[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])); } } @@ -141,7 +142,7 @@ return np; } -static int smp_iSeries_probe(void) +static void smp_iSeries_probe(void) { unsigned i; unsigned np; @@ -151,13 +152,13 @@ for (i=0; i < MAX_PACAS; ++i) { lpPaca = paca[i].xLpPacaPtr; if ( lpPaca->xDynProcStatus < 2 ) { + paca[i].active = 1; ++np; paca[i].next_jiffy_update_tb = paca[0].next_jiffy_update_tb; } } - + smp_tb_synchronized = 1; - return np; } static void smp_iSeries_kick_cpu(int nr) @@ -197,8 +198,10 @@ ppc_md.smp_probe = smp_iSeries_probe; ppc_md.smp_kick_cpu = smp_iSeries_kick_cpu; ppc_md.smp_setup_cpu = smp_iSeries_setup_cpu; - +#ifdef CONFIG_PPC_ISERIES +#warning fix for iseries naca->processorCount = smp_iSeries_numProcs(); +#endif } @@ -226,13 +229,10 @@ } } -static int -smp_chrp_probe(void) +static void smp_chrp_probe(void) { - if (naca->processorCount > 1) + if (ppc64_is_smp) openpic_request_IPIs(); - - return naca->processorCount; } static void @@ -259,14 +259,14 @@ extern struct gettimeofday_struct do_gtod; -static void smp_space_timers( unsigned nr ) +static void smp_space_timers() { - unsigned long offset, i; - - offset = tb_ticks_per_jiffy / nr; - for ( i=1; iplatform == PLATFORM_PSERIES_LPAR) { /* timebases already synced under the hypervisor. */ paca[cpu_nr].next_jiffy_update_tb = tb_last_stamp = get_tb(); - if (cpu_nr == 0) { + if (cpu_nr == boot_cpuid) { do_gtod.tb_orig_stamp = tb_last_stamp; /* Should update do_gtod.stamp_xsec. * For now we leave it which means the time can be some @@ -287,9 +287,9 @@ } smp_tb_synchronized = 1; } else { - if (cpu_nr == 0) { + if (cpu_nr == boot_cpuid) { /* wait for all the others */ - while (atomic_read(&ready) < smp_num_cpus) + while (atomic_read(&ready) < num_online_cpus()) barrier(); atomic_set(&ready, 1); /* freeze the timebase */ @@ -297,9 +297,9 @@ mb(); frozen = 1; set_tb(0, 0); - paca[0].next_jiffy_update_tb = 0; - smp_space_timers(smp_num_cpus); - while (atomic_read(&ready) < smp_num_cpus) + paca[boot_cpuid].next_jiffy_update_tb = 0; + smp_space_timers(); + while (atomic_read(&ready) < num_online_cpus()) barrier(); /* thaw the timebase again */ rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); @@ -323,8 +323,8 @@ if (OpenPIC_Addr) { do_openpic_setup_cpu(); } else { - if (cpu_nr > 0) - xics_setup_cpu(); + if (cpu_nr != boot_cpuid) + xics_setup_cpu(); } } @@ -333,7 +333,10 @@ { int i; - for (i = 0; i < smp_num_cpus; ++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())) { @@ -344,10 +347,8 @@ } } -static int -smp_xics_probe(void) +static void smp_xics_probe(void) { - return naca->processorCount; } /* This is called very early */ @@ -427,7 +428,7 @@ static void stop_this_cpu(void *dummy) { - __cli(); + local_irq_disable(); while (1) ; } @@ -435,7 +436,6 @@ void smp_send_stop(void) { smp_call_function(stop_this_cpu, NULL, 1, 0); - smp_num_cpus = 1; } /* @@ -473,7 +473,7 @@ { struct call_data_struct data; - int ret = -1, cpus = smp_num_cpus-1; + int ret = -1, cpus = num_online_cpus()-1; int timeout; if (!cpus) @@ -560,29 +560,23 @@ void __init smp_boot_cpus(void) { - int i, cpu_nr; + int i, cpu_nr = 0; struct task_struct *p; printk("Entering SMP Mode...\n"); - smp_num_cpus = 1; - smp_store_cpu_info(0); - cpu_online_map = 1UL; + smp_store_cpu_info(boot_cpuid); + cpu_callin_map[boot_cpuid] = 1; - /* - * assume for now that the first cpu booted is - * cpu 0, the master -- Cort - */ - cpu_callin_map[0] = 1; /* XXX buggy - Anton */ current_thread_info()->cpu = 0; for (i = 0; i < NR_CPUS; i++) { paca[i].prof_counter = 1; paca[i].prof_multiplier = 1; - if(i != 0) { + if (i != boot_cpuid) { /* - * Processor 0's segment table is statically + * the boot cpu segment table is statically * initialized to real address 0x5000. The * Other processor's tables are created and * initialized here. @@ -595,36 +589,37 @@ } /* - * XXX very rough. On POWER4 we optimise tlb flushes for - * tasks that only run on one cpu so we increase decay ticks. + * XXX very rough. */ - if (__is_processor(PV_POWER4)) - cache_decay_ticks = HZ/50; - else - cache_decay_ticks = HZ/100; + cache_decay_ticks = HZ/100; - /* Probe arch for CPUs */ - cpu_nr = ppc_md.smp_probe(); + ppc_md.smp_probe(); + for (i = 0; i < NR_CPUS; i++) { + if (paca[i].active) + cpu_nr++; + } printk("Probe found %d CPUs\n", cpu_nr); - /* - * only check for cpus we know exist. We keep the callin map - * with cpus at the bottom -- Cort - */ - if (cpu_nr > max_cpus) - cpu_nr = max_cpus; - #ifdef CONFIG_ISERIES - smp_space_timers( cpu_nr ); + smp_space_timers(); #endif printk("Waiting for %d CPUs\n", cpu_nr-1); - for ( i = 1 ; i < cpu_nr; i++ ) { + for (i = 1 ; i < NR_CPUS; i++) { int c; struct pt_regs regs; + if (!paca[i].active) + continue; + + if (i == boot_cpuid) + continue; + + if (num_online_cpus() >= max_cpus) + break; + /* create a process for the processor */ /* we don't care about the values in regs since we'll never reschedule the forked task. */ @@ -668,16 +663,15 @@ { printk("Processor %d found.\n", i); /* this sync's the decr's -- Cort */ - smp_num_cpus++; } else { printk("Processor %d is stuck.\n", i); } } - /* Setup CPU 0 last (important) */ - ppc_md.smp_setup_cpu(0); - - if (smp_num_cpus < 2) { + /* Setup boot cpu last (important) */ + ppc_md.smp_setup_cpu(boot_cpuid); + + if (num_online_cpus() < 2) { tb_last_stamp = get_tb(); smp_tb_synchronized = 1; } @@ -699,15 +693,16 @@ smp_store_cpu_info(cpu); set_dec(paca[cpu].default_decr); - cpu_callin_map[cpu] = 1; set_bit(smp_processor_id(), &cpu_online_map); + smp_mb(); + cpu_callin_map[cpu] = 1; ppc_md.smp_setup_cpu(cpu); while(!smp_commenced) { barrier(); } - __sti(); + local_irq_enable(); } /* intel needs this */ @@ -729,7 +724,7 @@ { } -int __init setup_profiling_timer(unsigned int multiplier) +int setup_profiling_timer(unsigned int multiplier) { return 0; } diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c --- a/arch/ppc64/kernel/stab.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/stab.c Wed Jul 24 14:03:39 2002 @@ -25,8 +25,6 @@ int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid); void make_slbe(unsigned long esid, unsigned long vsid, int large); -#define cpu_has_slb() (__is_processor(PV_POWER4)) - /* * Build an entry for the base kernel segment and put it into * the segment table or SLB. All other segment table or SLB @@ -371,7 +369,7 @@ /* Force previous translations to complete. DRENG */ asm volatile("isync" : : : "memory"); - __save_and_cli(flags); + local_irq_save(flags); if (get_paca()->stab_cache_pointer != 0xff && !STAB_PRESSURE) { int i; unsigned char *segments = get_paca()->xSegments; @@ -417,7 +415,7 @@ } get_paca()->stab_cache_pointer = 0; - __restore_flags(flags); + local_irq_restore(flags); } if (ppc64_stab_preload) diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c Wed Jul 24 14:03:39 2002 +++ b/arch/ppc64/kernel/time.c Wed Jul 24 14:03:39 2002 @@ -53,7 +53,6 @@ #include #include #include -#include #ifdef CONFIG_PPC_ISERIES #include #endif @@ -183,9 +182,9 @@ #ifdef CONFIG_PPC_ISERIES /* - * This function recalibrates the timebase based on the 49-bit time-of-day value in the Titan chip. - * The Titan is much more accurate than the value returned by the service processor for the - * timebase frequency. + * This function recalibrates the timebase based on the 49-bit time-of-day + * value in the Titan chip. The Titan is much more accurate than the value + * returned by the service processor for the timebase frequency. */ static void iSeries_tb_recal(void) @@ -256,7 +255,7 @@ unsigned long cpu = lpaca->xPacaIndex; struct ItLpQueue * lpq; - irq_enter(cpu); + irq_enter(); #ifndef CONFIG_PPC_ISERIES if (!user_mode(regs)) @@ -270,7 +269,7 @@ #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); #endif - if (cpu == 0) { + if (cpu == boot_cpuid) { write_lock(&xtime_lock); tb_last_stamp = lpaca->next_jiffy_update_tb; do_timer(regs); @@ -292,7 +291,7 @@ if (lpq && ItLpQueue_isLpIntPending(lpq)) lpEvent_count += ItLpQueue_process(lpq, regs); - irq_exit(cpu); + irq_exit(); if (softirq_pending(cpu)) do_softirq(); @@ -485,10 +484,10 @@ * After adjtimex is called, adjust the conversion of tb ticks * to microseconds to keep do_gettimeofday synchronized * with ntpd. - + * * Use the time_adjust, time_freq and time_offset computed by adjtimex to * adjust the frequency. -*/ + */ /* #define DEBUG_PPC_ADJTIMEX 1 */ @@ -531,8 +530,11 @@ /* Compute parts per million frequency adjustment to match time_adjust */ singleshot_ppm = tickadj * HZ; - /* The adjustment should be tickadj*HZ to match the code in linux/kernel/timer.c, but - experiments show that this is too large. 3/4 of tickadj*HZ seems about right */ + /* + * The adjustment should be tickadj*HZ to match the code in + * linux/kernel/timer.c, but experiments show that this is too + * large. 3/4 of tickadj*HZ seems about right + */ singleshot_ppm -= singleshot_ppm / 4; /* Use SHIFT_USEC to get it into the same units as time_freq */ singleshot_ppm <<= SHIFT_USEC; diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/kernel/traps.c Wed Jul 24 14:03:38 2002 @@ -172,8 +172,9 @@ if (!user_mode(regs)) { /* Attempt to recover if the interrupt is recoverable */ if (regs->msr & MSR_RI) { - if (__is_processor(PV_POWER4) && - power4_handle_mce(regs)) + if ((__is_processor(PV_POWER4) || + __is_processor(PV_POWER4p)) && + power4_handle_mce(regs)) return; } diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Wed Jul 24 14:03:35 2002 +++ b/arch/ppc64/kernel/xics.c Wed Jul 24 14:03:35 2002 @@ -340,7 +340,7 @@ /* Find the server numbers for the boot cpu. */ for (np = find_type_devices("cpu"); np; np = np->next) { ireg = (uint *)get_property(np, "reg", &ilen); - if (ireg && ireg[0] == hard_smp_processor_id()) { + if (ireg && ireg[0] == smp_processor_id()) { ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); i = ilen / sizeof(int); if (ireg && i > 0) { @@ -357,6 +357,7 @@ np = find_type_devices("interrupt-controller"); if (!np) { printk(KERN_WARNING "xics: no ISA Interrupt Controller\n"); + xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { ireg = (uint *) get_property(np, "interrupts", 0); @@ -371,10 +372,12 @@ if (naca->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP - for (i = 0; i < naca->processorCount; ++i) { + for (i = 0; i < NR_CPUS; ++i) { + if (!paca[i].active) + continue; xics_info.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); + __ioremap((ulong)inodes[i].addr, + (ulong)inodes[i].size, _PAGE_NO_CACHE); } #else xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); @@ -395,7 +398,7 @@ for (; i < NR_IRQS; ++i) irq_desc[i].handler = &xics_pic; - ops->cppr_info(0, 0xff); + ops->cppr_info(boot_cpuid, 0xff); iosync(); if (xics_irq_8259_cascade != -1) { if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action, @@ -420,23 +423,6 @@ i8259_init(); } -/* - * Find first logical cpu and return its physical cpu number - */ -static inline u32 physmask(u32 cpumask) -{ - int i; - - for (i = 0; i < smp_num_cpus; ++i, cpumask >>= 1) { - if (cpumask & 1) - return get_hard_smp_processor_id(i); - } - - printk(KERN_ERR "xics_set_affinity: invalid irq mask\n"); - - return default_distrib_server; -} - void xics_set_affinity(unsigned int virq, unsigned long cpumask) { irq_desc_t *desc = irq_desc + virq; @@ -462,10 +448,13 @@ } /* For the moment only implement delivery to all cpus or one cpu */ - if (cpumask == 0xffffffff) + if (cpumask == 0xffffffff) { newmask = default_distrib_server; - else - newmask = physmask(cpumask); + } else { + if (!(cpumask & cpu_online_map)) + goto out; + newmask = find_first_bit(&cpumask, 32); + } status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, newmask, xics_status[1]); diff -Nru a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S --- a/arch/ppc64/lib/string.S Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/lib/string.S Wed Jul 24 14:03:36 2002 @@ -171,11 +171,11 @@ add r4,r0,r4 subf r6,r0,r6 srwi r0,r4,2 + andi. r4,r4,3 mtctr r0 - bdz 6f + bdz 7f 1: stwu r5,4(r6) bdnz 1b -6: andi. r4,r4,3 /* clear byte sized chunks */ 7: cmpwi 0,r4,0 beqlr @@ -184,14 +184,20 @@ 8: stbu r5,1(r6) bdnz 8b blr -99: li r3,-EFAULT +90: mr r3,r4 + blr +91: mfctr r3 + slwi r3,r3,2 + add r3,r3,r4 + blr +92: mfctr r3 blr .section __ex_table,"a" .align 3 - .llong 11b,99b - .llong 1b,99b - .llong 8b,99b + .llong 11b,90b + .llong 1b,91b + .llong 8b,92b .text _GLOBAL(__strncpy_from_user) diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/mm/fault.c Wed Jul 24 14:03:36 2002 @@ -121,16 +121,18 @@ */ switch (handle_mm_fault(mm, vma, address, is_write)) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/mm/init.c Wed Jul 24 14:03:38 2002 @@ -1,6 +1,4 @@ /* - * - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * @@ -59,11 +57,10 @@ #include #include #include +#include #include -#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10) - #ifdef CONFIG_PPC_ISERIES #include #endif @@ -76,15 +73,10 @@ extern pgd_t swapper_pg_dir[]; extern char __init_begin, __init_end; -extern char __chrp_begin, __chrp_end; -extern char __openfirmware_begin, __openfirmware_end; -extern struct _of_tce_table of_tce_table[]; extern char _start[], _end[]; extern char _stext[], etext[]; extern struct task_struct *current_set[NR_CPUS]; -void mm_init_ppc64(void); - extern pgd_t ioremap_dir[]; pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir; @@ -107,7 +99,7 @@ void show_mem(void) { - int i,free = 0,total = 0,reserved = 0; + int i,total = 0,reserved = 0; int shared = 0, cached = 0; printk("Mem-info:\n"); @@ -120,13 +112,10 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!atomic_read(&mem_map[i].count)) - free++; - else - shared += atomic_read(&mem_map[i].count) - 1; + else if (page_count(mem_map+i)) + shared += page_count(mem_map+i) - 1; } printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); @@ -179,7 +168,7 @@ else { ea = ioremap_bot; ioremap_bot += size; - } + } if ((flags & _PAGE_PRESENT) == 0) flags |= pgprot_val(PAGE_KERNEL); @@ -196,9 +185,9 @@ void iounmap(void *addr) { #ifdef CONFIG_PPC_ISERIES - /* iSeries I/O Remap is a noop */ + /* iSeries I/O Remap is a noop */ return; -#else +#else /* DRENG / PPPBBB todo */ return; #endif @@ -229,7 +218,7 @@ /* 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); ppc_md.make_pte(htab_data.htab, (vsid << 28) | (ea & 0xFFFFFFF), // va (NOT the ea) @@ -302,7 +291,7 @@ } } -struct tlb_batch_data tlb_batch_array[NR_CPUS][MAX_BATCH_FLUSH]; +struct ppc64_tlb_batch ppc64_tlb_batch[NR_CPUS]; void __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) @@ -312,81 +301,69 @@ pte_t *ptep; pte_t pte; unsigned long pgd_end, pmd_end; - unsigned long context; - int i = 0; - struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0]; + unsigned long context = 0; + struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; + unsigned long i = 0; int local = 0; - if ( start >= end ) - panic("flush_tlb_range: start (%016lx) greater than end (%016lx)\n", start, end ); - - if ( REGION_ID(start) != REGION_ID(end) ) - panic("flush_tlb_range: start (%016lx) and end (%016lx) not in same region\n", start, end ); - - context = 0; - - switch( REGION_ID(start) ) { + switch(REGION_ID(start)) { case VMALLOC_REGION_ID: - pgd = pgd_offset_k( start ); + pgd = pgd_offset_k(start); break; case IO_REGION_ID: - pgd = pgd_offset_i( start ); + pgd = pgd_offset_i(start); break; case USER_REGION_ID: - pgd = pgd_offset( mm, start ); + pgd = pgd_offset(mm, start); context = mm->context; /* XXX are there races with checking cpu_vm_mask? - Anton */ - if (mm->cpu_vm_mask == (1 << smp_processor_id())) { + if (mm->cpu_vm_mask == (1 << smp_processor_id())) 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 ) + if (pgd_end > end) pgd_end = end; - if ( !pgd_none( *pgd ) ) { - pmd = pmd_offset( pgd, start ); + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, start); do { - pmd_end = ( start + PMD_SIZE ) & PMD_MASK; - if ( pmd_end > end ) + pmd_end = (start + PMD_SIZE) & PMD_MASK; + if (pmd_end > end) pmd_end = end; - if ( !pmd_none( *pmd ) ) { - ptep = pte_offset_kernel( pmd, start ); + if (!pmd_none(*pmd)) { + ptep = pte_offset_kernel(pmd, start); do { - if ( pte_val(*ptep) & _PAGE_HASHPTE ) { + if (pte_val(*ptep) & _PAGE_HASHPTE) { pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0)); - if ( pte_val(pte) & _PAGE_HASHPTE ) { - ptes->pte = pte; - ptes->addr = start; - ptes++; + if (pte_val(pte) & _PAGE_HASHPTE) { + batch->pte[i] = pte; + batch->addr[i] = start; i++; - if (i == MAX_BATCH_FLUSH) { - flush_hash_range(context, MAX_BATCH_FLUSH, local); + if (i == PPC64_TLB_BATCH_NR) { + flush_hash_range(context, i, local); i = 0; - ptes = &tlb_batch_array[smp_processor_id()][0]; } } } start += PAGE_SIZE; ++ptep; - } while ( start < pmd_end ); - } - else + } while (start < pmd_end); + } else { start = pmd_end; + } ++pmd; - } while ( start < pgd_end ); - } - else + } while (start < pgd_end); + } else { start = pgd_end; + } ++pgd; - } while ( start < end ); + } while (start < end); if (i) flush_hash_range(context, i, local); @@ -435,12 +412,12 @@ * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT) * are stored on a stack/queue for easy allocation and deallocation. */ - mmu_context_queue.lock = SPIN_LOCK_UNLOCKED; - mmu_context_queue.head = 0; - mmu_context_queue.tail = NUM_USER_CONTEXT-1; - mmu_context_queue.size = NUM_USER_CONTEXT; + mmu_context_queue.lock = SPIN_LOCK_UNLOCKED; + 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; + mmu_context_queue.elements[index] = index+FIRST_USER_CONTEXT; } /* Setup guard pages for the Paca's */ @@ -463,7 +440,6 @@ unsigned long start, bootmap_pages; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; - PPCDBG(PPCDBG_MMINIT, "do_init_bootmem: start\n"); /* * Find an area to use for the bootmem bitmap. Calculate the size of * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE. @@ -472,21 +448,16 @@ bootmap_pages = bootmem_bootmap_pages(total_pages); start = (unsigned long)__a2p(lmb_alloc(bootmap_pages<physicalMemorySize); - boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); - PPCDBG(PPCDBG_MMINIT, "\tboot_mapsize = 0x%lx\n", boot_mapsize); /* add all physical memory to the bootmem map */ - for (i=0; i < lmb.memory.cnt ;i++) { + for (i=0; i < lmb.memory.cnt; i++) { unsigned long physbase, size; unsigned long type = lmb.memory.region[i].type; @@ -497,19 +468,14 @@ size = lmb.memory.region[i].size; free_bootmem(physbase, size); } + /* reserve the sections we're already using */ - for (i=0; i < lmb.reserved.cnt ;i++) { + for (i=0; i < lmb.reserved.cnt; i++) { unsigned long physbase = lmb.reserved.region[i].physbase; unsigned long size = lmb.reserved.region[i].size; -#if 0 /* PPPBBB */ - if ( (physbase == 0) && (size < (16<<20)) ) { - size = 16 << 20; - } -#endif + reserve_bootmem(physbase, size); } - - PPCDBG(PPCDBG_MMINIT, "do_init_bootmem: end\n"); } /* @@ -522,7 +488,7 @@ /* * All pages are DMA-able so we put them all in the DMA zone. */ - zones_size[0] = lmb_end_of_DRAM() >> PAGE_SHIFT; + 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); @@ -554,14 +520,6 @@ totalram_pages += free_all_bootmem(); - ifppcdebug(PPCDBG_MMINIT) { - udbg_printf("mem_init: totalram_pages = 0x%lx\n", totalram_pages); - udbg_printf("mem_init: va_rtas_base = 0x%lx\n", va_rtas_base); - udbg_printf("mem_init: va_rtas_end = 0x%lx\n", PAGE_ALIGN(va_rtas_base+rtas.size)); - udbg_printf("mem_init: pinned start = 0x%lx\n", __va(0)); - udbg_printf("mem_init: pinned end = 0x%lx\n", PAGE_ALIGN(klimit)); - } - if ( sysmap_size ) for (addr = (unsigned long)sysmap; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; @@ -582,7 +540,7 @@ datapages++; } - printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", + printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10), codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), initpages<< (PAGE_SHIFT-10), @@ -613,6 +571,12 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page) { + if (cpu_has_noexecute()) + return; + + if ((vma->vm_flags & VM_EXEC) == 0) + return; + if (page->mapping && !PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { __flush_dcache_icache(page_address(page)); @@ -620,15 +584,35 @@ } } -void clear_user_page(void *page, unsigned long vaddr) +void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); + + /* XXX we shouldnt have to do this, but glibc requires it */ + if (cpu_has_noexecute()) + clear_bit(PG_arch_1, &pg->flags); + else + __flush_dcache_icache(page); } -void copy_user_page(void *vto, void *vfrom, unsigned long vaddr) +void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *pg) { copy_page(vto, vfrom); - __flush_dcache_icache(vto); + + /* + * Unfortunately we havent always marked our GOT and PLT sections + * as executable, so we need to flush all file regions - Anton + */ +#if 0 + if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0)) + return; +#endif + + if (cpu_has_noexecute()) + clear_bit(PG_arch_1, &pg->flags); + else + __flush_dcache_icache(vto); } void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, @@ -642,7 +626,7 @@ extern pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea); int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - pte_t *ptep); + pte_t *ptep, unsigned long trap); /* * This is called at the end of handling a user page fault, when the @@ -670,5 +654,6 @@ ptep = find_linux_pte(pgdir, ea); vsid = get_vsid(vma->vm_mm->context, ea); - __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep); + __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep, + 0x300); } diff -Nru a/arch/ppc64/vmlinux.lds b/arch/ppc64/vmlinux.lds --- a/arch/ppc64/vmlinux.lds Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/vmlinux.lds Wed Jul 24 14:03:36 2002 @@ -1,4 +1,4 @@ -OUTPUT_ARCH(powerpc) +OUTPUT_ARCH(powerpc:common64) SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); /* Do we need any of these for elf? __DYNAMIC = 0; */ @@ -116,19 +116,6 @@ __per_cpu_end = .; . = ALIGN(4096); __init_end = .; - - __chrp_begin = .; - .text.chrp : { *(.text.chrp) } - .data.chrp : { *(.data.chrp) } - . = ALIGN(4096); - __chrp_end = .; - - . = ALIGN(4096); - __openfirmware_begin = .; - .text.openfirmware : { *(.text.openfirmware) } - .data.openfirmware : { *(.data.openfirmware) } - . = ALIGN(4096); - __openfirmware_end = .; __toc_start = .; .toc : diff -Nru a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h --- a/arch/ppc64/xmon/privinst.h Wed Jul 24 14:03:36 2002 +++ b/arch/ppc64/xmon/privinst.h Wed Jul 24 14:03:36 2002 @@ -6,7 +6,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include #define GETREG(reg) \ static inline unsigned long get_ ## reg (void) \ diff -Nru a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c --- a/arch/ppc64/xmon/start.c Wed Jul 24 14:03:38 2002 +++ b/arch/ppc64/xmon/start.c Wed Jul 24 14:03:38 2002 @@ -58,9 +58,9 @@ } static struct sysrq_key_op sysrq_xmon_op = { - handler: sysrq_handle_xmon, - help_msg: "xmon", - action_msg: "Entering xmon\n", + .handler = sysrq_handle_xmon, + .help_msg = "xmon", + .action_msg = "Entering xmon\n", }; void diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Wed Jul 24 14:03:37 2002 +++ b/arch/ppc64/xmon/xmon.c Wed Jul 24 14:03:37 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -123,11 +124,7 @@ static void mem_check(void); static void mem_find_real(void); static void mem_find_vsid(void); -static void mem_check_pagetable_vsids (void); -static void mem_map_check_slab(void); -static void mem_map_lock_pages(void); -static void mem_check_dup_rpn (void); static void debug_trace(void); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long); @@ -189,13 +186,6 @@ asm volatile("sync; isync"); } -extern inline void __delay(unsigned int loops) -{ - if (loops != 0) - __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : : - "r" (loops) : "ctr"); -} - /* (Ref: 64-bit PowerPC ELF ABI Spplement; Ian Lance Taylor, Zembu Labs). A PPC stack frame looks like this: @@ -440,11 +430,11 @@ xmon_irq(int irq, void *d, struct pt_regs *regs) { unsigned long flags; - __save_flags(flags); - __cli(); + local_save_flags(flags); + local_irq_disable(); printf("Keyboard interrupt\n"); xmon(regs); - __restore_flags(flags); + local_irq_restore(flags); } int @@ -552,7 +542,7 @@ } } - if (!__is_processor(PV_POWER4)) { + if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { if (dabr.enabled) set_dabr(dabr.address); if (iabr.enabled) @@ -569,7 +559,7 @@ if (naca->platform != PLATFORM_PSERIES) return; - if (!__is_processor(PV_POWER4)) { + if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { set_dabr(0); set_iabr(0); } @@ -642,27 +632,15 @@ case 'c': mem_check(); break; - case 'j': - mem_map_check_slab(); - break; case 'f': mem_find_real(); break; case 'e': mem_find_vsid(); break; - case 'r': - mem_check_dup_rpn(); - break; case 'i': show_mem(); break; - case 'o': - mem_check_pagetable_vsids (); - break; - case 'q': - mem_map_lock_pages() ; - break; default: termch = cmd; memex(); @@ -866,7 +844,7 @@ cmd = inchar(); switch (cmd) { case 'd': /* bd - hardware data breakpoint */ - if (__is_processor(PV_POWER4)) { + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { printf("Not implemented on POWER4\n"); break; } @@ -886,7 +864,7 @@ dabr.address = (dabr.address & ~7) | mode; break; case 'i': /* bi - hardware instr breakpoint */ - if (__is_processor(PV_POWER4)) { + if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { printf("Not implemented on POWER4\n"); break; } @@ -2456,249 +2434,6 @@ } } printf("\nDone -------------------\n"); -} - -void mem_map_check_slab() -{ - int i, slab_count; - - i = max_mapnr; - slab_count = 0; - - while (i-- > 0) { - if (PageSlab(mem_map+i)){ - printf(" slab entry - mem_map entry =%p \n", mem_map+i); - slab_count ++; - } - } - - printf(" count of pages for slab = %d \n", slab_count); -} - -void mem_map_lock_pages() -{ - int i, lock_count; - - i = max_mapnr; - lock_count = 0; - - while (i-- > 0) { - if (PageLocked(mem_map+i)){ - printf(" locked entry - mem_map entry =%p \n", mem_map+i); - lock_count ++; - } - } - - printf(" count of locked pages = %d \n", lock_count); -} - -void mem_check_dup_rpn () -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - HPTE *hpte1, *hpte2; - int dup_count; - struct task_struct *p; - unsigned long kernel_vsid_c0,kernel_vsid_c1,kernel_vsid_c2,kernel_vsid_c3; - unsigned long kernel_vsid_c4,kernel_vsid_c5,kernel_vsid_d,kernel_vsid_e; - unsigned long kernel_vsid_f; - unsigned long vsid0,vsid1,vsidB,vsid2; - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nHardware Page Table Check\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( hpte1->dw1.dw1.rpn <= last_rpn ) { - dup_count = 0; - for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { - if ( hpte2->dw0.dw0.v != 0 ) { - if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { - dup_count++; - } - } - } - if(dup_count > 5) { - printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" mem map array entry %p count = %d \n", - (mem_map+(hpte1->dw1.dw1.rpn)), (mem_map+(hpte1->dw1.dw1.rpn))->count); - for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { - if ( hpte2->dw0.dw0.v != 0 ) { - if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { - printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n", - hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1); - } - } - } - } - } else { - printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - if (xmon_interrupted()) - return; - } - - - - // print the kernel vsids - kernel_vsid_c0 = get_kernel_vsid(0xC000000000000000); - kernel_vsid_c1 = get_kernel_vsid(0xC000000010000000); - kernel_vsid_c2 = get_kernel_vsid(0xC000000020000000); - kernel_vsid_c3 = get_kernel_vsid(0xC000000030000000); - kernel_vsid_c4 = get_kernel_vsid(0xC000000040000000); - kernel_vsid_c5 = get_kernel_vsid(0xC000000050000000); - kernel_vsid_d = get_kernel_vsid(0xD000000000000000); - kernel_vsid_e = get_kernel_vsid(0xE000000000000000); - kernel_vsid_f = get_kernel_vsid(0xF000000000000000); - - printf(" kernel vsid - seg c0 = %lx\n", kernel_vsid_c0 ); - printf(" kernel vsid - seg c1 = %lx\n", kernel_vsid_c1 ); - printf(" kernel vsid - seg c2 = %lx\n", kernel_vsid_c2 ); - printf(" kernel vsid - seg c3 = %lx\n", kernel_vsid_c3 ); - printf(" kernel vsid - seg c4 = %lx\n", kernel_vsid_c4 ); - printf(" kernel vsid - seg c5 = %lx\n", kernel_vsid_c5 ); - printf(" kernel vsid - seg d = %lx\n", kernel_vsid_d ); - printf(" kernel vsid - seg e = %lx\n", kernel_vsid_e ); - printf(" kernel vsid - seg f = %lx\n", kernel_vsid_f ); - - - // print a list of valid vsids for the tasks - read_lock(&tasklist_lock); - for_each_task(p) - if(p->mm) { - struct mm_struct *mm = p->mm; - printf(" task = %p mm = %lx pgd %lx\n", - p, mm, mm->pgd); - vsid0 = get_vsid( mm->context, 0 ); - vsid1 = get_vsid( mm->context, 0x10000000 ); - vsid2 = get_vsid( mm->context, 0x20000000 ); - vsidB = get_vsid( mm->context, 0xB0000000 ); - printf(" context = %lx vsid seg 0 = %lx\n", mm->context, vsid0 ); - printf(" vsid seg 1 = %lx\n", vsid1 ); - printf(" vsid seg 2 = %lx\n", vsid2 ); - printf(" vsid seg 2 = %lx\n", vsidB ); - - printf("\n"); - }; - read_unlock(&tasklist_lock); - - printf("\nDone -------------------\n"); -} - - - -void mem_check_pagetable_vsids () -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - struct task_struct *p; - unsigned long valid_table_count,invalid_table_count,bogus_rpn_count; - int found; - unsigned long user_address_table_count,kernel_page_table_count; - unsigned long pt_vsid; - HPTE *hpte1; - - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nHardware Page Table Check\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - valid_table_count = 0; - invalid_table_count = 0; - bogus_rpn_count = 0; - user_address_table_count = 0; - kernel_page_table_count = 0; - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - valid_table_count++; - if ( hpte1->dw1.dw1.rpn <= last_rpn ) { - pt_vsid = (hpte1->dw0.dw0.avpn) >> 5; - if ((pt_vsid == get_kernel_vsid(0xC000000000000000)) | - (pt_vsid == get_kernel_vsid(0xC000000010000000)) | - (pt_vsid == get_kernel_vsid(0xC000000020000000)) | - (pt_vsid == get_kernel_vsid(0xC000000030000000)) | - (pt_vsid == get_kernel_vsid(0xC000000040000000)) | - (pt_vsid == get_kernel_vsid(0xC000000050000000)) | - (pt_vsid == get_kernel_vsid(0xD000000000000000)) | - (pt_vsid == get_kernel_vsid(0xE000000000000000)) | - (pt_vsid == get_kernel_vsid(0xF000000000000000)) ) { - kernel_page_table_count ++; - } else { - read_lock(&tasklist_lock); - found = 0; - for_each_task(p) { - if(p->mm && (found == 0)) { - struct mm_struct *mm = p->mm; - - if ((pt_vsid == get_vsid( mm->context, 0 )) | - (pt_vsid == get_vsid( mm->context, 0x10000000 )) | - (pt_vsid == get_vsid( mm->context, 0x20000000 )) | - (pt_vsid == get_vsid( mm->context, 0x30000000 )) | - (pt_vsid == get_vsid( mm->context, 0x40000000 )) | - (pt_vsid == get_vsid( mm->context, 0x50000000 )) | - (pt_vsid == get_vsid( mm->context, 0x60000000 )) | - (pt_vsid == get_vsid( mm->context, 0x70000000 )) | - (pt_vsid == get_vsid( mm->context, 0x80000000 )) | - (pt_vsid == get_vsid( mm->context, 0x90000000 )) | - (pt_vsid == get_vsid( mm->context, 0xA0000000 )) | - (pt_vsid == get_vsid( mm->context, 0xB0000000 ))) { - user_address_table_count ++; - found = 1; - } - } - } - read_unlock(&tasklist_lock); - if (found == 0) - { - printf(" vsid not found vsid = %lx, hpte = %p \n", - pt_vsid,hpte1); - printf(" rpn in entry = %lx \n", hpte1->dw1.dw1.rpn); - printf(" mem map address = %lx \n", mem_map + (hpte1->dw1.dw1.rpn)); - - } else // found - { - } - - } // good rpn - - } else { - bogus_rpn_count ++; - } - } else { - invalid_table_count++; - } - } - - - printf(" page table valid counts - valid entries = %lx invalid entries = %lx \n", - valid_table_count, invalid_table_count); - - printf(" bogus rpn entries ( probably io) = %lx \n", bogus_rpn_count); - - - - printf(" page table counts - kernel entries = %lx user entries = %lx \n", - kernel_page_table_count, user_address_table_count); - - printf("\nDone -------------------\n"); - } static void debug_trace(void) { diff -Nru a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c --- a/arch/s390/kernel/irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/s390/kernel/irq.c Wed Jul 24 14:03:38 2002 @@ -161,9 +161,9 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); check_smp_invalidate(cpu); if (atomic_read(&global_irq_count)) continue; @@ -249,10 +249,10 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if (flags & (1 << EFLAGS_I_SHIFT)) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!in_irq()) get_irqlock(cpu); } @@ -263,7 +263,7 @@ if (!in_irq()) release_irqlock(smp_processor_id()); - __sti(); + local_irq_enable(); } /* @@ -279,7 +279,7 @@ int local_enabled; unsigned long flags; - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags >> EFLAGS_I_SHIFT) & 1; /* default to local */ retval = 2 + local_enabled; @@ -305,10 +305,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx (%08lx)\n", diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c --- a/arch/s390/kernel/setup.c Wed Jul 24 14:03:36 2002 +++ b/arch/s390/kernel/setup.c Wed Jul 24 14:03:36 2002 @@ -86,7 +86,7 @@ if (test_and_set_bit(nr,&cpu_initialized)) { printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr); - for (;;) __sti(); + for (;;) local_irq_enable(); } cpus_initialized++; diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c --- a/arch/s390/kernel/traps.c Wed Jul 24 14:03:37 2002 +++ b/arch/s390/kernel/traps.c Wed Jul 24 14:03:37 2002 @@ -280,7 +280,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (regs->psw.mask & PSW_PROBLEM_STATE) { struct task_struct *tsk = current; @@ -416,7 +416,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (regs->psw.mask & PSW_PROBLEM_STATE) get_user(*((__u16 *) opcode), location); @@ -477,7 +477,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (regs->psw.mask & PSW_PROBLEM_STATE) { get_user(*((__u16 *) opcode), location); @@ -540,7 +540,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (MACHINE_HAS_IEEE) __asm__ volatile ("stfpc %0\n\t" diff -Nru a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c --- a/arch/s390/mm/fault.c Wed Jul 24 14:03:39 2002 +++ b/arch/s390/mm/fault.c Wed Jul 24 14:03:39 2002 @@ -199,7 +199,7 @@ * task's user address space, so we can switch on the * interrupts again and then search the VMAs */ - __sti(); + local_irq_enable(); down_read(&mm->mmap_sem); @@ -528,7 +528,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (subcode & 0x0080) { /* signal bit is set -> a page has been swapped in by VM */ diff -Nru a/arch/s390x/kernel/irq.c b/arch/s390x/kernel/irq.c --- a/arch/s390x/kernel/irq.c Wed Jul 24 14:03:39 2002 +++ b/arch/s390x/kernel/irq.c Wed Jul 24 14:03:39 2002 @@ -162,9 +162,9 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); check_smp_invalidate(cpu); if (atomic_read(&global_irq_count)) continue; @@ -250,10 +250,10 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if (flags & (1UL << EFLAGS_I_SHIFT)) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!in_irq()) get_irqlock(cpu); } @@ -264,7 +264,7 @@ if (!in_irq()) release_irqlock(smp_processor_id()); - __sti(); + local_irq_enable(); } /* @@ -280,7 +280,7 @@ int local_enabled; unsigned long flags; - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags >> EFLAGS_I_SHIFT) & 1; /* default to local */ retval = 2 + local_enabled; @@ -306,10 +306,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx (%08lx)\n", diff -Nru a/arch/s390x/kernel/setup.c b/arch/s390x/kernel/setup.c --- a/arch/s390x/kernel/setup.c Wed Jul 24 14:03:37 2002 +++ b/arch/s390x/kernel/setup.c Wed Jul 24 14:03:37 2002 @@ -86,7 +86,7 @@ if (test_and_set_bit(nr,&cpu_initialized)) { printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr); - for (;;) __sti(); + for (;;) local_irq_enable(); } cpus_initialized++; diff -Nru a/arch/s390x/kernel/traps.c b/arch/s390x/kernel/traps.c --- a/arch/s390x/kernel/traps.c Wed Jul 24 14:03:39 2002 +++ b/arch/s390x/kernel/traps.c Wed Jul 24 14:03:39 2002 @@ -282,7 +282,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (regs->psw.mask & PSW_PROBLEM_STATE) { struct task_struct *tsk = current; @@ -419,7 +419,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); /* WARNING don't change this check back to */ /* int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE); */ @@ -452,7 +452,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); __asm__ volatile ("stfpc %0\n\t" : "=m" (current->thread.fp_regs.fpc)); diff -Nru a/arch/s390x/mm/fault.c b/arch/s390x/mm/fault.c --- a/arch/s390x/mm/fault.c Wed Jul 24 14:03:37 2002 +++ b/arch/s390x/mm/fault.c Wed Jul 24 14:03:37 2002 @@ -199,7 +199,7 @@ * task's user address space, so we can switch on the * interrupts again and then search the VMAs */ - __sti(); + local_irq_enable(); down_read(&mm->mmap_sem); @@ -440,7 +440,7 @@ * now safely switch on interrupts. */ if (regs->psw.mask & PSW_PROBLEM_STATE) - __sti(); + local_irq_enable(); if (subcode & 0x0080) { /* signal bit is set -> a page has been swapped in by VM */ diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c --- a/arch/sh/kernel/irq.c Wed Jul 24 14:03:37 2002 +++ b/arch/sh/kernel/irq.c Wed Jul 24 14:03:37 2002 @@ -130,7 +130,7 @@ status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -139,7 +139,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); irq_exit(cpu, irq); diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c --- a/arch/sh/kernel/process.c Wed Jul 24 14:03:39 2002 +++ b/arch/sh/kernel/process.c Wed Jul 24 14:03:39 2002 @@ -46,13 +46,13 @@ if (need_resched()) break; } else { - __cli(); + local_irq_disable(); while (!need_resched()) { - __sti(); + local_irq_enable(); asm volatile("sleep" : : : "memory"); - __cli(); + local_irq_disable(); } - __sti(); + local_irq_enable(); } schedule(); check_pgt_cache(); diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c --- a/arch/sparc/kernel/irq.c Wed Jul 24 14:03:35 2002 +++ b/arch/sparc/kernel/irq.c Wed Jul 24 14:03:35 2002 @@ -231,7 +231,7 @@ /* - * We have to allow irqs to arrive between __sti and __cli + * We have to allow irqs to arrive between local_irq_enable and local_irq_disable */ #define SYNC_OTHER_CORES(x) barrier() @@ -276,9 +276,9 @@ show("get_irqlock"); count = (~0 >> 1); } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); } goto again; } @@ -302,11 +302,11 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if ((flags & PSR_PIL) != PSR_PIL) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -318,7 +318,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -333,7 +333,7 @@ unsigned long flags, retval; unsigned long local_enabled = 0; - __save_flags(flags); + local_save_flags(flags); if ((flags & PSR_PIL) != PSR_PIL) local_enabled = 1; @@ -361,10 +361,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: { diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c --- a/arch/sparc/kernel/pcic.c Wed Jul 24 14:03:35 2002 +++ b/arch/sparc/kernel/pcic.c Wed Jul 24 14:03:35 2002 @@ -780,7 +780,7 @@ prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); prom_halt(); } - __sti(); + local_irq_enable(); } static __inline__ unsigned long do_gettimeoffset(void) diff -Nru a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c --- a/arch/sparc/kernel/smp.c Wed Jul 24 14:03:37 2002 +++ b/arch/sparc/kernel/smp.c Wed Jul 24 14:03:37 2002 @@ -253,7 +253,7 @@ /* Stopping processors. */ void smp_stop_cpu_irq(void) { - __sti(); + local_irq_enable(); while(1) barrier(); } diff -Nru a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c --- a/arch/sparc/kernel/sun4d_irq.c Wed Jul 24 14:03:35 2002 +++ b/arch/sparc/kernel/sun4d_irq.c Wed Jul 24 14:03:35 2002 @@ -488,14 +488,14 @@ * has copied the firmwares level 14 vector into boot cpu's * trap table, we must fix this now or we get squashed. */ - __save_and_cli(flags); + local_irq_save(flags); patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ trap_table->inst_one = lvl14_save[0]; trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; local_flush_cache_all(); - __restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -539,7 +539,7 @@ void __init sun4d_init_IRQ(void) { - __cli(); + local_irq_disable(); BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c --- a/arch/sparc/kernel/sun4d_smp.c Wed Jul 24 14:03:36 2002 +++ b/arch/sparc/kernel/sun4d_smp.c Wed Jul 24 14:03:36 2002 @@ -144,7 +144,7 @@ local_flush_cache_all(); local_flush_tlb_all(); - __sti(); /* We don't allow PIL 14 yet */ + local_irq_enable(); /* We don't allow PIL 14 yet */ while(!smp_commenced) barrier(); @@ -182,7 +182,7 @@ if (boot_cpu_id) current_set[0] = NULL; - __sti(); + local_irq_enable(); cpu_present_map = 0; for(i=0; i < linux_num_cpus; i++) cpu_present_map |= (1<inst_one = lvl14_save[0]; trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; local_flush_cache_all(); - __restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -315,7 +315,7 @@ int num_regs; struct resource r; - __cli(); + local_irq_disable(); if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || (ie_node = prom_getchild (ie_node)) == 0 || (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { diff -Nru a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c --- a/arch/sparc/kernel/sun4m_smp.c Wed Jul 24 14:03:37 2002 +++ b/arch/sparc/kernel/sun4m_smp.c Wed Jul 24 14:03:37 2002 @@ -127,7 +127,7 @@ local_flush_cache_all(); local_flush_tlb_all(); - __sti(); + local_irq_enable(); } extern int cpu_idle(void *unused); @@ -153,7 +153,7 @@ printk("Entering SMP Mode...\n"); - __sti(); + local_irq_enable(); cpu_present_map = 0; for(i=0; i < linux_num_cpus; i++) diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c --- a/arch/sparc/kernel/time.c Wed Jul 24 14:03:38 2002 +++ b/arch/sparc/kernel/time.c Wed Jul 24 14:03:38 2002 @@ -437,7 +437,7 @@ #endif /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ - __sti(); + local_irq_enable(); } void __init time_init(void) diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c --- a/arch/sparc/mm/srmmu.c Wed Jul 24 14:03:35 2002 +++ b/arch/sparc/mm/srmmu.c Wed Jul 24 14:03:35 2002 @@ -657,7 +657,7 @@ FLUSH_BEGIN(mm) flush_user_windows(); - __save_and_cli(flags); + local_irq_save(flags); octx = srmmu_get_context(); srmmu_set_context(mm->context); a = 0x20; b = 0x40; c = 0x60; @@ -681,7 +681,7 @@ "r" (e), "r" (f), "r" (g)); } while(faddr); srmmu_set_context(octx); - __restore_flags(flags); + local_irq_restore(flags); FLUSH_END } @@ -694,7 +694,7 @@ FLUSH_BEGIN(mm) flush_user_windows(); - __save_and_cli(flags); + local_irq_save(flags); octx = srmmu_get_context(); srmmu_set_context(mm->context); a = 0x20; b = 0x40; c = 0x60; @@ -723,7 +723,7 @@ start += SRMMU_PMD_SIZE; } srmmu_set_context(octx); - __restore_flags(flags); + local_irq_restore(flags); FLUSH_END } @@ -736,7 +736,7 @@ FLUSH_BEGIN(mm) flush_user_windows(); - __save_and_cli(flags); + local_irq_save(flags); octx = srmmu_get_context(); srmmu_set_context(mm->context); a = 0x20; b = 0x40; c = 0x60; @@ -762,7 +762,7 @@ "r" (e), "r" (f), "r" (g)); } while(line != page); srmmu_set_context(octx); - __restore_flags(flags); + local_irq_restore(flags); FLUSH_END } diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c --- a/arch/sparc64/kernel/irq.c Wed Jul 24 14:03:37 2002 +++ b/arch/sparc64/kernel/irq.c Wed Jul 24 14:03:37 2002 @@ -634,9 +634,9 @@ show("get_irqlock"); count = (~0 >> 1); } - __sti(); + local_irq_enable(); SYNC_OTHER_ULTRAS(cpu); - __cli(); + local_irq_disable(); } goto again; } @@ -648,10 +648,10 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if(flags == 0) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (! local_irq_count(cpu)) get_irqlock(cpu); } @@ -663,14 +663,14 @@ if (! local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } unsigned long __global_save_flags(void) { unsigned long flags, local_enabled, retval; - __save_flags(flags); + local_save_flags(flags); local_enabled = ((flags == 0) ? 1 : 0); retval = 2 + local_enabled; if (! local_irq_count(smp_processor_id())) { @@ -692,10 +692,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: { diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c Wed Jul 24 14:03:35 2002 +++ b/arch/sparc64/kernel/smp.c Wed Jul 24 14:03:35 2002 @@ -199,7 +199,7 @@ smp_setup_percpu_timer(); - __sti(); + local_irq_enable(); calibrate_delay(); smp_store_cpu_info(cpuid); @@ -243,7 +243,7 @@ int cpucount = 0, i; printk("Entering UltraSMPenguin Mode...\n"); - __sti(); + local_irq_enable(); smp_store_cpu_info(boot_cpu_id); if (linux_num_cpus == 1) { @@ -1222,7 +1222,7 @@ __get_free_pages(GFP_KERNEL, order = get_order(ecache_size)); if (flush_base != 0UL) { - __save_and_cli(flags); + local_irq_save(flags); /* Scan twice the size once just to get the TLB entries * loaded and make sure the second scan measures pure misses. @@ -1271,7 +1271,7 @@ : "g1", "g2", "g3", "g5"); } - __restore_flags(flags); + local_irq_restore(flags); raw = (tick2 - tick1); diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Wed Jul 24 14:03:38 2002 +++ b/arch/sparc64/kernel/time.c Wed Jul 24 14:03:38 2002 @@ -432,7 +432,7 @@ return; } - __save_and_cli(flags); + local_irq_save(flags); cbus = central_bus; if (cbus != NULL) @@ -610,7 +610,7 @@ set_system_time(); - __restore_flags(flags); + local_irq_restore(flags); } extern void init_timers(void (*func)(int, void *, struct pt_regs *), diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c Wed Jul 24 14:03:37 2002 +++ b/arch/sparc64/mm/init.c Wed Jul 24 14:03:37 2002 @@ -1411,7 +1411,7 @@ */ pt = phys_base | _PAGE_VALID | _PAGE_SZ4MB; pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W; - __save_and_cli(flags); + local_irq_save(flags); if (tlb_type == spitfire) { __asm__ __volatile__( " stxa %1, [%0] %3\n" @@ -1469,7 +1469,7 @@ : "memory"); } } - __restore_flags(flags); + local_irq_restore(flags); /* Now set kernel pgd to upper alias so physical page computations * work. diff -Nru a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c --- a/arch/sparc64/prom/misc.c Wed Jul 24 14:03:39 2002 +++ b/arch/sparc64/prom/misc.c Wed Jul 24 14:03:39 2002 @@ -52,7 +52,7 @@ { unsigned long flags; - __save_and_cli(flags); + local_irq_save(flags); #ifdef CONFIG_SUN_CONSOLE if(!serial_console && prom_palette) @@ -75,7 +75,7 @@ prom_palette (0); #endif - __restore_flags(flags); + local_irq_restore(flags); } #ifdef CONFIG_SMP diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Wed Jul 24 14:03:36 2002 +++ b/arch/x86_64/kernel/apic.c Wed Jul 24 14:03:36 2002 @@ -474,13 +474,13 @@ apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); - __save_flags(flags); - __cli(); + local_save_flags(flags); + local_irq_disable(); disable_local_APIC(); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_ENABLE; wrmsr(MSR_IA32_APICBASE, l, h); - __restore_flags(flags); + local_irq_restore(flags); } static void apic_pm_resume(void *data) @@ -488,8 +488,8 @@ unsigned int l, h; unsigned long flags; - __save_flags(flags); - __cli(); + local_save_flags(flags); + local_irq_disable(); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; @@ -512,7 +512,7 @@ apic_write(APIC_LVTERR, apic_pm_state.apic_lvterr); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); - __restore_flags(flags); + local_irq_restore(flags); if (apic_pm_state.perfctr_pmdev) pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data); } @@ -785,8 +785,8 @@ unsigned long flags; int delta; - __save_flags(flags); - __sti(); + local_save_flags(flags); + local_irq_enable(); /* * ok, Intel has some smart code in their APIC that knows * if a CPU was in 'hlt' lowpower mode, and this increases @@ -825,7 +825,7 @@ printk("CPU%d\n", smp_processor_id(), t0, t1, delta, slice, clocks); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -916,7 +916,7 @@ printk("Using local APIC timer interrupts.\n"); using_apic_timer = 1; - __cli(); + local_irq_disable(); calibration_result = calibrate_APIC_clock(); /* @@ -924,7 +924,7 @@ */ setup_APIC_timer((void *)(u64)calibration_result); - __sti(); + local_irq_enable(); /* and update all other cpus */ smp_call_function(setup_APIC_timer, (void *)(u64)calibration_result, 1, 1); diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Wed Jul 24 14:03:38 2002 +++ b/arch/x86_64/kernel/irq.c Wed Jul 24 14:03:38 2002 @@ -254,7 +254,7 @@ # define SYNC_OTHER_CORES(x) udelay(x+1) #else /* - * We have to allow irqs to arrive between __sti and __cli + * We have to allow irqs to arrive between local_irq_enable and local_irq_disable */ # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") #endif @@ -282,9 +282,9 @@ show("wait_on_irq"); count = ~0; } - __sti(); + local_irq_enable(); SYNC_OTHER_CORES(cpu); - __cli(); + local_irq_disable(); if (irqs_running()) continue; if (global_irq_lock) @@ -356,10 +356,10 @@ { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); if (flags & (1 << EFLAGS_IF_SHIFT)) { int cpu = smp_processor_id(); - __cli(); + local_irq_disable(); if (!local_irq_count(cpu)) get_irqlock(cpu); } @@ -371,7 +371,7 @@ if (!local_irq_count(cpu)) release_irqlock(cpu); - __sti(); + local_irq_enable(); } /* @@ -388,7 +388,7 @@ unsigned long flags; int cpu = smp_processor_id(); - __save_flags(flags); + local_save_flags(flags); local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1; /* default to local */ retval = 2 + local_enabled; @@ -413,10 +413,10 @@ __global_sti(); break; case 2: - __cli(); + local_irq_disable(); break; case 3: - __sti(); + local_irq_enable(); break; default: printk("global_restore_flags: %08lx (%08lx)\n", @@ -442,7 +442,7 @@ status = 1; /* Force the "do bottom halves" bit */ if (!(action->flags & SA_INTERRUPT)) - __sti(); + local_irq_enable(); do { status |= action->flags; @@ -451,7 +451,7 @@ } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); + local_irq_disable(); irq_exit(0, irq); diff -Nru a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c --- a/arch/x86_64/kernel/ldt.c Wed Jul 24 14:03:39 2002 +++ b/arch/x86_64/kernel/ldt.c Wed Jul 24 14:03:39 2002 @@ -132,7 +132,8 @@ void release_segments(struct mm_struct *mm) { if (mm->context.size) { - clear_LDT(); + if (mm == current->active_mm) + clear_LDT(); if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else diff -Nru a/arch/x86_64/kernel/mtrr.c b/arch/x86_64/kernel/mtrr.c --- a/arch/x86_64/kernel/mtrr.c Wed Jul 24 14:03:37 2002 +++ b/arch/x86_64/kernel/mtrr.c Wed Jul 24 14:03:37 2002 @@ -117,8 +117,8 @@ u64 cr0; /* Disable interrupts locally */ - __save_flags(ctxt->flags); - __cli(); + local_save_flags(ctxt->flags); + local_irq_disable(); /* Save value of CR4 and clear Page Global Enable (bit 7) */ if (cpu_has_pge) { @@ -156,7 +156,7 @@ write_cr4 (ctxt->cr4val); /* Re-enable interrupts locally (if enabled previously) */ - __restore_flags(ctxt->flags); + local_irq_restore(ctxt->flags); } diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Wed Jul 24 14:03:35 2002 +++ b/arch/x86_64/kernel/process.c Wed Jul 24 14:03:35 2002 @@ -89,11 +89,11 @@ void default_idle(void) { if (!hlt_counter) { - __cli(); + local_irq_disable(); if (!need_resched()) safe_halt(); else - __sti(); + local_irq_enable(); } } @@ -106,7 +106,7 @@ { int oldval; - __sti(); + local_irq_enable(); /* * Deal with another CPU just having chosen a thread to diff -Nru a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c --- a/arch/x86_64/kernel/smp.c Wed Jul 24 14:03:36 2002 +++ b/arch/x86_64/kernel/smp.c Wed Jul 24 14:03:36 2002 @@ -97,8 +97,8 @@ unsigned long cfg; unsigned long flags; - __save_flags(flags); - __cli(); + local_save_flags(flags); + local_irq_disable(); /* * Wait for idle. @@ -120,7 +120,7 @@ * Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around(APIC_ICR, cfg); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -438,7 +438,7 @@ * Remove this CPU: */ clear_bit(smp_processor_id(), &cpu_online_map); - __cli(); + local_irq_disable(); disable_local_APIC(); for(;;) __asm__("hlt"); for (;;); @@ -453,9 +453,9 @@ smp_call_function(stop_this_cpu, NULL, 1, 0); smp_num_cpus = 1; - __cli(); + local_irq_disable(); disable_local_APIC(); - __sti(); + local_irq_enable(); } /* diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Wed Jul 24 14:03:35 2002 +++ b/arch/x86_64/kernel/traps.c Wed Jul 24 14:03:35 2002 @@ -344,7 +344,7 @@ printk("%s: %04lx\n", str, err & 0xffff); cpu = smp_processor_id(); /* racy, but better than risking deadlock. */ - __cli(); + local_irq_disable(); if (!spin_trylock(&die_lock)) { if (cpu == die_owner) /* nested oops. should stop eventually */; diff -Nru a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c --- a/arch/x86_64/pci/direct.c Wed Jul 24 14:03:39 2002 +++ b/arch/x86_64/pci/direct.c Wed Jul 24 14:03:39 2002 @@ -306,7 +306,7 @@ unsigned int tmp; unsigned long flags; - __save_flags(flags); __cli(); + local_save_flags(flags); local_irq_disable(); /* * Check if configuration type 1 works. @@ -318,7 +318,7 @@ if (inl (0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) { outl (tmp, 0xCF8); - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_INFO "PCI: Using configuration type 1\n"); if (!request_region(0xCF8, 8, "PCI conf1")) return NULL; @@ -336,7 +336,7 @@ outb (0x00, 0xCFA); if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 && pci_sanity_check(&pci_direct_conf2)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_INFO "PCI: Using configuration type 2\n"); if (!request_region(0xCF8, 4, "PCI conf2")) return NULL; @@ -344,7 +344,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return NULL; } diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Wed Jul 24 14:03:39 2002 +++ b/drivers/Makefile Wed Jul 24 14:03:39 2002 @@ -8,7 +8,7 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ char/ block/ misc/ net/ media/ +obj-y += base/ serial/ char/ block/ misc/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_IDE) += ide/ diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Wed Jul 24 14:03:36 2002 +++ b/drivers/acorn/block/mfmhd.c Wed Jul 24 14:03:36 2002 @@ -184,8 +184,6 @@ #define NEED_1_RECAL -2 #define NEED_2_RECAL -3 int cylinder; - unsigned int access_count; - unsigned int busy; struct { char recal; char report; @@ -197,7 +195,6 @@ static struct hd_struct mfm[MFM_MAXDRIVES << 6]; static int mfm_sizes[MFM_MAXDRIVES << 6]; -static DECLARE_WAIT_QUEUE_HEAD(mfm_wait_open); /* Stuff from the assembly routines */ extern unsigned int hdc63463_baseaddress; /* Controller base address */ @@ -1195,22 +1192,11 @@ return -EFAULT; return 0; - case BLKSECTGET: - return put_user(max_sectors[major][minor], (long *) arg); - case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; return mfm_reread_partitions(dev); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKROSET: - case BLKROGET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; } @@ -1219,24 +1205,8 @@ static int mfm_open(struct inode *inode, struct file *file) { int dev = DEVICE_NR(minor(inode->i_rdev)); - if (dev >= mfm_drives) return -ENODEV; - - while (mfm_info[dev].busy) - sleep_on (&mfm_wait_open); - - mfm_info[dev].access_count++; - return 0; -} - -/* - * Releasing a block device means we sync() it, so that it can safely - * be forgotten about... - */ -static int mfm_release(struct inode *inode, struct file *file) -{ - mfm_info[DEVICE_NR(minor(inode->i_rdev))].access_count--; return 0; } @@ -1254,10 +1224,11 @@ * since if there are any non-ADFS partitions on the disk, this won't work! * Hence, I want to get rid of this... */ -void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads, - unsigned long discsize, unsigned int secsize) +void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, + unsigned char heads, unsigned int secsize) { - int drive = minor(dev) >> 6; + int drive = MINOR(bdev->bd_dev) >> 6; + unsigned long disksize = bdev->bd_inode->i_size; if (mfm_info[drive].cylinders == 1) { mfm_info[drive].sectors = secsptrack; @@ -1265,7 +1236,7 @@ mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize); if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) { - printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6)); + printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + drive); /* These values are fairly arbitary, but are there so that if your * lucky you can pick apart your disc to find out what is going on - @@ -1295,7 +1266,6 @@ { owner: THIS_MODULE, open: mfm_open, - release: mfm_release, ioctl: mfm_ioctl, }; @@ -1424,38 +1394,19 @@ /* * This routine is called to flush all partitions and partition tables * for a changed MFM disk, and then re-read the new partition table. - * If we are revalidating due to an ioctl, we have USAGE == 1. */ static int mfm_reread_partitions(kdev_t dev) { - unsigned int start, i, maxp, target = DEVICE_NR(minor(dev)); - unsigned long flags; - - local_irq_save(flags); - if (mfm_info[target].busy || mfm_info[target].access_count > 1) { - local_irq_restore (flags); - return -EBUSY; - } - mfm_info[target].busy = 1; - local_irq_restore (flags); - - maxp = 1 << mfm_gendisk.minor_shift; - start = target << mfm_gendisk.minor_shift; - - for (i = maxp - 1; i >= 0; i--) { - int minor = start + i; - invalidate_device (mk_kdev(MAJOR_NR, minor), 1); - mfm_gendisk.part[minor].start_sect = 0; - mfm_gendisk.part[minor].nr_sects = 0; - } - + unsigned int unit = DEVICE_NR(minor(dev)); + kdev_t device = mk_kdev(MAJOR_NR, unit << mfm_gendisk.minor_shift); + int err = dev_lock_part(device); + if (err) + return err; + wipe_partitions(device); /* Divide by 2, since sectors are 2 times smaller than usual ;-) */ - - grok_partitions(&mfm_gendisk, target, 1<<6, mfm_info[target].heads * - mfm_info[target].cylinders * mfm_info[target].sectors / 2); - - mfm_info[target].busy = 0; - wake_up (&mfm_wait_open); + grok_partitions(device, mfm_info[unit].heads * + mfm_info[unit].cylinders * mfm_info[unit].sectors / 2); + dev_unlock_part(device); return 0; } diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c Wed Jul 24 14:03:38 2002 +++ b/drivers/acpi/processor.c Wed Jul 24 14:03:38 2002 @@ -416,7 +416,7 @@ * Interrupts must be disabled during bus mastering calculations and * for C2/C3 transitions. */ - __cli(); + local_irq_disable(); cx = &(pr->power.states[pr->power.state]); @@ -461,7 +461,7 @@ * issues (e.g. floppy DMA transfer overrun/underrun). */ if (pr->power.bm_activity & cx->demotion.threshold.bm) { - __sti(); + local_irq_enable(); next_state = cx->demotion.state; goto end; } @@ -497,7 +497,7 @@ /* Get end time (ticks) */ t2 = inl(acpi_fadt.Xpm_tmr_blk.address); /* Re-enable interrupts */ - __sti(); + local_irq_enable(); /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; break; @@ -516,13 +516,13 @@ /* Enable bus master arbitration */ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); /* Re-enable interrupts */ - __sti(); + local_irq_enable(); /* Compute time (ticks) that we were actually asleep */ sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; break; default: - __sti(); + local_irq_enable(); return; } @@ -1170,7 +1170,7 @@ pr->throttling.state = 0; - __cli(); + local_irq_disable(); duty_mask = pr->throttling.state_count - 1; @@ -1192,7 +1192,7 @@ pr->throttling.state = state; - __sti(); + local_irq_enable(); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state is T%d (%d%% throttling applied)\n", @@ -1225,7 +1225,7 @@ if (state == pr->throttling.state) return_VALUE(0); - __cli(); + local_irq_disable(); /* * Calculate the duty_value and duty_mask. @@ -1267,7 +1267,7 @@ pr->throttling.state = state; - __sti(); + local_irq_enable(); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state set to T%d (%d%%)\n", state, diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/DAC960.c Wed Jul 24 14:03:39 2002 @@ -2055,29 +2055,20 @@ static void DAC960_RegisterDisk(DAC960_Controller_T *Controller, int LogicalDriveNumber) { - if (Controller->FirmwareType == DAC960_V1_Controller) - { + long size; + if (Controller->FirmwareType == DAC960_V1_Controller) { if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) return; - register_disk(&Controller->GenericDiskInfo, - DAC960_KernelDevice(Controller->ControllerNumber, - LogicalDriveNumber, 0), - DAC960_MaxPartitions, - &DAC960_BlockDeviceOperations, - Controller->V1.LogicalDriveInformation - [LogicalDriveNumber].LogicalDriveSize); - } - else - { + size = Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveSize; + } else { DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; if (LogicalDeviceInfo == NULL) return; - register_disk(&Controller->GenericDiskInfo, - DAC960_KernelDevice(Controller->ControllerNumber, - LogicalDriveNumber, 0), - DAC960_MaxPartitions, - &DAC960_BlockDeviceOperations, - LogicalDeviceInfo->ConfigurableDeviceSize); - } + size = LogicalDeviceInfo->ConfigurableDeviceSize; + } + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, size); } @@ -5399,15 +5390,9 @@ LogicalDeviceInfo->ConfigurableDeviceSize / (Geometry.heads * Geometry.sectors); } - Geometry.start = get_start_sect(Inode->i_rdev); + Geometry.start = get_start_sect(Inode->i_bdev); return (copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)) ? -EFAULT : 0); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKBSZGET: - case BLKBSZSET: - return blk_ioctl(Inode->i_bdev, Request, Argument); case BLKRRPART: /* Re-Read Partition Table. */ diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/acsi.c Wed Jul 24 14:03:38 2002 @@ -68,6 +68,7 @@ #include #include /* for HDIO_GETGEO */ #include +#include #include #include @@ -248,8 +249,6 @@ static int acsi_sizes[MAX_DEV<<4] = { 0, }; static struct hd_struct acsi_part[MAX_DEV<<4] = { {0,0}, }; static int access_count[MAX_DEV] = { 0, }; -static char busy[MAX_DEV] = { 0, }; -static DECLARE_WAIT_QUEUE_HEAD(busy_wait); static int CurrentNReq; static int CurrentNSect; @@ -372,13 +371,13 @@ static int acsi_change_blk_size( int target, int lun); static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd ); static void acsi_geninit(void); -static int revalidate_acsidisk( int dev, int maxusage ); -static int acsi_revalidate (dev_t); +static int revalidate_acsidisk( kdev_t dev, int maxusage ); +static int acsi_revalidate (kdev_t); /************************* End of Prototypes **************************/ -struct timer_list acsi_timer = { NULL, NULL, 0, 0, acsi_times_out }; +struct timer_list acsi_timer = { function: acsi_times_out }; #ifdef CONFIG_ATARI_SLM @@ -786,7 +785,7 @@ status = acsi_getstatus(); if (status != 0) { - int dev = DEVICE_NR(minor(CURRENT->rq_dev)); + int dev = minor(CURRENT->rq_dev); printk( KERN_ERR "ad%c: ", dev+'a' ); if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, acsi_info[dev].lun)) @@ -817,7 +816,7 @@ status = acsi_getstatus(); if (status != 0) { - int dev = DEVICE_NR(minor(CURRENT->rq_dev)); + int dev = minor(CURRENT->rq_dev); printk( KERN_ERR "ad%c: ", dev+'a' ); if (!acsi_reqsense( acsi_buffer, acsi_info[dev].target, acsi_info[dev].lun)) @@ -969,7 +968,7 @@ return; } - if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) + if (major(CURRENT->rq_dev) != MAJOR_NR) panic(DEVICE_NAME ": request list destroyed"); if (CURRENT->bh) { if (!CURRENT->bh && !buffer_locked(CURRENT->bh)) @@ -978,26 +977,26 @@ dev = minor(CURRENT->rq_dev); block = CURRENT->sector; - if (DEVICE_NR(dev) >= NDevices || + if (dev >= NDevices || block+CURRENT->nr_sectors >= acsi_part[dev].nr_sects) { #ifdef DEBUG printk( "ad%c: attempted access for blocks %d...%ld past end of device at block %ld.\n", - DEVICE_NR(dev)+'a', + dev+'a', block, block + CURRENT->nr_sectors - 1, acsi_part[dev].nr_sects); #endif end_request(CURRENT, 0); goto repeat; } - if (acsi_info[DEVICE_NR(dev)].changed) { + if (acsi_info[dev].changed) { printk( KERN_NOTICE "ad%c: request denied because cartridge has " - "been changed.\n", DEVICE_NR(dev)+'a' ); + "been changed.\n", dev+'a' ); end_request(CURRENT, 0); goto repeat; } - target = acsi_info[DEVICE_NR(dev)].target; - lun = acsi_info[DEVICE_NR(dev)].lun; + target = acsi_info[dev].target; + lun = acsi_info[dev].lun; /* Find out how many sectors should be transferred from/to * consecutive buffers and thus can be done with a single command. @@ -1045,7 +1044,7 @@ CurrentBuffer = buffer; CurrentNSect = nsect; - if (CURRENT->cmd == WRITE) { + if (rq_data_dir(CURRENT) == WRITE) { CMDSET_TARG_LUN( write_cmd, target, lun ); CMDSET_BLOCK( write_cmd, block ); CMDSET_LEN( write_cmd, nsect ); @@ -1062,7 +1061,7 @@ SET_TIMER(); return; } - if (CURRENT->cmd == READ) { + if (rq_data_dir(CURRENT) == READ) { CMDSET_TARG_LUN( read_cmd, target, lun ); CMDSET_BLOCK( read_cmd, block ); CMDSET_LEN( read_cmd, nsect ); @@ -1090,11 +1089,12 @@ static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) -{ int dev; +{ + dev_t dev; if (!inode) return -EINVAL; - dev = DEVICE_NR(minor(inode->i_rdev)); + dev = minor(inode->i_rdev); if (dev >= NDevices) return -EINVAL; switch (cmd) { @@ -1107,7 +1107,7 @@ put_user( 64, &geo->heads ); put_user( 32, &geo->sectors ); put_user( acsi_info[dev].size >> 11, &geo->cylinders ); - put_user(get_start_sect(inode->i_rdev), &geo->start); + put_user(get_start_sect(inode->i_bdev), &geo->start); return 0; } @@ -1118,14 +1118,6 @@ put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id ); return 0; - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - case BLKRRPART: /* Re-read partition tables */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -1157,12 +1149,10 @@ int device; struct acsi_info_struct *aip; - device = DEVICE_NR(minor(inode->i_rdev)); + device = minor(inode->i_rdev); if (device >= NDevices) return -ENXIO; aip = &acsi_info[device]; - while (busy[device]) - sleep_on(&busy_wait); if (access_count[device] == 0 && aip->removable) { #if 0 @@ -1195,7 +1185,7 @@ static int acsi_release( struct inode * inode, struct file * file ) { - int device = DEVICE_NR(minor(inode->i_rdev)); + int device = minor(inode->i_rdev); if (--access_count[device] == 0 && acsi_info[device].removable) acsi_prevent_removal(device, 0); return( 0 ); @@ -1221,9 +1211,9 @@ stdma_release(); } -static int acsi_media_change (dev_t dev) +static int acsi_media_change (kdev_t dev) { - int device = DEVICE_NR(minor(dev)); + int device = minor(dev); struct acsi_info_struct *aip; aip = &acsi_info[device]; @@ -1803,10 +1793,6 @@ } #endif -#define DEVICE_BUSY busy[device] -#define USAGE access_count[device] -#define GENDISK_STRUCT acsi_gendisk - /* * This routine is called to flush all partitions and partition tables * for a changed scsi disk, and then re-read the new partition table. @@ -1826,26 +1812,17 @@ * */ -static int revalidate_acsidisk( int dev, int maxusage ) +static int revalidate_acsidisk(kdev_t dev, int maxusage ) { - int device; - struct gendisk * gdev; - int res; - struct acsi_info_struct *aip; - - device = DEVICE_NR(minor(dev)); - aip = &acsi_info[device]; - gdev = &GENDISK_STRUCT; + int unit = DEVICE_NR(minor(dev)); + struct acsi_info_struct *aip = &acsi_info[unit]; + kdev_t device = mk_kdev(MAJOR_NR, unit<<4); + int res = dev_lock_part(device); - cli(); - if (DEVICE_BUSY || USAGE > maxusage) { - sti(); - return -EBUSY; - }; - DEVICE_BUSY = 1; - sti(); + if (res < 0) + return res; - res = wipe_partitions(dev); + res = wipe_partitions(device); stdma_lock( NULL, NULL ); @@ -1862,15 +1839,14 @@ stdma_release(); if (!res) - grok_partitions(dev, aip->size); + grok_partitions(device, aip->size); - DEVICE_BUSY = 0; - wake_up(&busy_wait); + dev_unlock_part(device); return res; } -static int acsi_revalidate (dev_t dev) +static int acsi_revalidate (kdev_t dev) { return revalidate_acsidisk (dev, 0); } diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c --- a/drivers/block/amiflop.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/amiflop.c Wed Jul 24 14:03:38 2002 @@ -71,6 +71,7 @@ #include #include #include +#include #include #include @@ -1849,8 +1850,6 @@ /* init ms timer */ ciaa.crb = 8; /* one-shot, stop */ - - (void)do_floppy; /* avoid warning about unused variable */ return 0; } diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c --- a/drivers/block/ataflop.c Wed Jul 24 14:03:36 2002 +++ b/drivers/block/ataflop.c Wed Jul 24 14:03:36 2002 @@ -76,6 +76,7 @@ #include #include #include +#include /* for invalidate_buffers() */ #include #include @@ -358,7 +359,7 @@ static void fd_select_drive( int drive ); static void fd_deselect( void ); static void fd_motor_off_timer( unsigned long dummy ); -static void check_change( void ); +static void check_change( unsigned long dummy ); static __inline__ void set_head_settle_flag( void ); static __inline__ int get_head_settle_flag( void ); static void floppy_irq (int irq, void *dummy, struct pt_regs *fp); @@ -378,7 +379,6 @@ static void fd_times_out( unsigned long dummy ); static void finish_fdc( void ); static void finish_fdc_done( int dummy ); -static void floppy_off( unsigned int nr); static __inline__ void copy_buffer( void *from, void *to); static void setup_req_params( int drive ); static void redo_fd_request( void); @@ -539,7 +539,7 @@ * as possible) and keep track of the current state of the write protection. */ -static void check_change( void ) +static void check_change( unsigned long dummy ) { static int drive = 0; @@ -1339,9 +1339,6 @@ static int fd_ref[4] = { 0,0,0,0 }; static int fd_device[4] = { 0,0,0,0 }; -/* dummy for blk.h */ -static void floppy_off( unsigned int nr) {} - /* The detection of disk changes is a dark chapter in Atari history :-( * Because the "Drive ready" signal isn't present in the Atari @@ -1458,9 +1455,6 @@ if (major(CURRENT->rq_dev) != MAJOR_NR) panic(DEVICE_NAME ": request list destroyed"); - if (CURRENT->bh && !buffer_locked(CURRENT->bh)) - panic(DEVICE_NAME ": block not locked"); - device = minor(CURRENT->rq_dev); drive = device & 3; type = device >> 2; @@ -1507,7 +1501,7 @@ del_timer( &motor_off_timer ); ReqCnt = 0; - ReqCmd = CURRENT->cmd; + ReqCmd = rq_data_dir(CURRENT); ReqBlock = CURRENT->sector; ReqBuffer = CURRENT->buffer; setup_req_params( drive ); @@ -1559,12 +1553,6 @@ struct floppy_struct setprm; device = inode->i_rdev; - switch (cmd) { - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - return blk_ioctl(inode->i_bdev, cmd, param); - } drive = minor (device); type = drive >> 2; drive &= 3; @@ -2008,7 +1996,6 @@ UseTrackbuffer ? "" : "no "); config_types(); - (void)do_floppy; /* avoid warning about unused variable */ return 0; } diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c --- a/drivers/block/blkpg.c Wed Jul 24 14:03:35 2002 +++ b/drivers/block/blkpg.c Wed Jul 24 14:03:35 2002 @@ -69,8 +69,9 @@ struct gendisk *g; long long ppstart, pplength; long pstart, plength; - int i, drive, first_minor, end_minor, minor; + int i; kdev_t dev = to_kdev_t(bdev->bd_dev); + struct hd_struct *part; /* convert bytes to sectors, check for fit in a hd_struct */ ppstart = (p->start >> 9); @@ -85,37 +86,32 @@ g = get_gendisk(dev); if (!g) return -ENXIO; + part = g->part + minor(dev); /* existing drive? */ - drive = (minor(dev) >> g->minor_shift); - first_minor = (drive << g->minor_shift); - end_minor = first_minor + (1 << g->minor_shift); - if (drive >= g->nr_real) - return -ENXIO; /* drive and partition number OK? */ - if (first_minor != minor(dev)) + if (bdev != bdev->bd_contains) return -EINVAL; if (p->pno <= 0 || p->pno >= (1 << g->minor_shift)) return -EINVAL; /* partition number in use? */ - minor = first_minor + p->pno; - if (g->part[minor].nr_sects != 0) + if (part[p->pno].nr_sects != 0) return -EBUSY; /* overlap? */ - for (i=first_minor+1; ipart[i].start_sect || - pstart >= g->part[i].start_sect + g->part[i].nr_sects)) + for (i = 1; i < (1<minor_shift); i++) + if (!(pstart+plength <= part[i].start_sect || + pstart >= part[i].start_sect + part[i].nr_sects)) return -EBUSY; /* all seems OK */ - g->part[minor].start_sect = pstart; - g->part[minor].nr_sects = plength; + part[p->pno].start_sect = pstart; + part[p->pno].nr_sects = plength; if (g->sizes) - g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9)); - devfs_register_partitions (g, first_minor, 0); + g->sizes[minor(dev)+p->pno] = (plength >> (BLOCK_SIZE_BITS-9)); + devfs_register_partitions (g, minor(dev), 0); return 0; } @@ -133,33 +129,27 @@ { kdev_t dev = to_kdev_t(bdev->bd_dev); struct gendisk *g; - kdev_t devp; struct block_device *bdevp; - int drive, first_minor, minor; + struct hd_struct *part; int holder; /* find the drive major */ g = get_gendisk(dev); if (!g) return -ENXIO; + part = g->part + minor(dev); - /* drive and partition number OK? */ - drive = (minor(dev) >> g->minor_shift); - first_minor = (drive << g->minor_shift); - - if (first_minor != minor(dev)) + if (bdev != bdev->bd_contains) return -EINVAL; if (p->pno <= 0 || p->pno >= (1 << g->minor_shift)) return -EINVAL; /* existing drive and partition? */ - minor = first_minor + p->pno; - if (drive >= g->nr_real || g->part[minor].nr_sects == 0) + if (part[p->pno].nr_sects == 0) return -ENXIO; /* partition in use? Incomplete check for now. */ - devp = mk_kdev(major(dev), minor); - bdevp = bdget(kdev_t_to_nr(devp)); + bdevp = bdget(MKDEV(major(dev), minor(dev) + p->pno)); if (!bdevp) return -ENOMEM; if (bd_claim(bdevp, &holder) < 0) { @@ -171,11 +161,11 @@ fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - g->part[minor].start_sect = 0; - g->part[minor].nr_sects = 0; + part[p->pno].start_sect = 0; + part[p->pno].nr_sects = 0; if (g->sizes) - g->sizes[minor] = 0; - devfs_register_partitions (g, first_minor, 0); + g->sizes[minor(dev) + p->pno] = 0; + devfs_register_partitions (g, minor(dev), 0); bd_release(bdevp); bdput(bdevp); @@ -223,10 +213,6 @@ int holder; struct backing_dev_info *bdi; - intval = block_ioctl(bdev, cmd, arg); - if (intval != -ENOTTY) - return intval; - switch (cmd) { case BLKROSET: if (!capable(CAP_SYS_ADMIN)) @@ -296,14 +282,6 @@ case BLKPG: return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg); - - /* - * deprecated, use the /proc/iosched interface instead - */ - case BLKELVGET: - case BLKELVSET: - return -ENOTTY; - case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ intval = block_size(bdev); @@ -330,5 +308,3 @@ return -EINVAL; } } - -EXPORT_SYMBOL(blk_ioctl); diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/cciss.c Wed Jul 24 14:03:39 2002 @@ -440,15 +440,6 @@ case BLKRRPART: return revalidate_logvol(inode->i_rdev, 1); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKBSZSET: - case BLKBSZGET: - case BLKROSET: - case BLKROGET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); case CCISS_GETPCIINFO: { cciss_pci_info_struct pciinfo; @@ -735,6 +726,10 @@ } /* Borrowed and adapted from sd.c */ +/* + * FIXME: we are missing the exclusion with ->open() here - it can happen + * just as we are rereading partition tables. + */ static int revalidate_logvol(kdev_t dev, int maxusage) { int ctlr, target; @@ -860,18 +855,9 @@ /* invalidate the devices and deregister the disk */ max_p = 1 << gdev->minor_shift; start = logvol << gdev->minor_shift; + wipe_partitions(mk_kdev(MAJOR_NR+ctlr, start)); for (i=max_p-1; i>=0; i--) - { - int minor = start+i; - kdev_t kdev = mk_kdev(MAJOR_NR+ctlr, minor); - // printk("invalidating( %d %d)\n", ctlr, minor); - invalidate_device(kdev, 1); - /* so open will now fail */ - h->sizes[minor] = 0; - /* so it will no longer appear in /proc/partitions */ - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - } + h->sizes[start + i] = 0; /* check to see if it was the last disk */ if (logvol == h->highest_lun) { @@ -1313,19 +1299,12 @@ hba[ctlr]->drv[logvol].usage_count = 0; max_p = 1 << gdev->minor_shift; start = logvol<< gdev->minor_shift; + kdev = mk_kdev(MAJOR_NR + ctlr, logvol<< gdev->minor_shift); - for(i=max_p-1; i>=0; i--) { - int minor = start+i; - kdev = mk_kdev(MAJOR_NR + ctlr, minor); - invalidate_device(kdev, 1); - gdev->part[minor].start_sect = 0; - gdev->part[minor].nr_sects = 0; - } - + wipe_partitions(kdev); ++hba[ctlr]->num_luns; gdev->nr_real = hba[ctlr]->highest_lun + 1; /* setup partitions per disk */ - kdev = mk_kdev(MAJOR_NR + ctlr, logvol<< gdev->minor_shift); grok_partitions(kdev, hba[ctlr]->drv[logvol].nr_blocks); kfree(ld_buff); @@ -1884,7 +1863,7 @@ goto queue; startio: - blk_stop_queue(q); + __blk_stop_queue(q); start_io(h); } diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Wed Jul 24 14:03:36 2002 +++ b/drivers/block/cpqarray.c Wed Jul 24 14:03:36 2002 @@ -918,7 +918,7 @@ goto queue_next; startio: - blk_stop_queue(q); + __blk_stop_queue(q); start_io(h); } @@ -1116,7 +1116,7 @@ put_user(diskinfo[0], &geo->heads); put_user(diskinfo[1], &geo->sectors); put_user(diskinfo[2], &geo->cylinders); - put_user(get_start_sect(inode->i_rdev), &geo->start); + put_user(get_start_sect(inode->i_bdev), &geo->start); return 0; case IDAGETDRVINFO: if (copy_to_user(&io->c.drv, &hba[ctlr]->drv[dsk], @@ -1157,16 +1157,6 @@ return(0); } - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKBSZSET: - case BLKBSZGET: - case BLKROSET: - case BLKROGET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; } @@ -1533,6 +1523,9 @@ } /* Borrowed and adapted from sd.c */ +/* + * FIXME: exclusion with ->open() + */ static int revalidate_logvol(kdev_t dev, int maxusage) { int ctlr, target; diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Wed Jul 24 14:03:36 2002 +++ b/drivers/block/floppy.c Wed Jul 24 14:03:36 2002 @@ -3468,12 +3468,6 @@ const char *outparam; /* parameters passed back to user space */ device = inode->i_rdev; - switch (cmd) { - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - return blk_ioctl(inode->i_bdev, cmd, param); - } type = TYPE(device); drive = DRIVE(device); @@ -4260,9 +4254,12 @@ CLEARSTRUCT(FDCS); FDCS->dtr = -1; FDCS->dor = 0x4; -#ifdef __sparc__ - /*sparcs don't have a DOR reset which we can fall back on to*/ - FDCS->version = FDC_82072A; +#if defined(__sparc__) || defined(__mc68000__) + /*sparcs/sun3x don't have a DOR reset which we can fall back on to*/ +#ifdef __mc68000__ + if (MACH_IS_SUN3X) +#endif + FDCS->version = FDC_82072A; #endif } diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/genhd.c Wed Jul 24 14:03:38 2002 @@ -117,31 +117,6 @@ EXPORT_SYMBOL(get_gendisk); - -unsigned long -get_start_sect(kdev_t dev) -{ - struct gendisk *gp; - - gp = get_gendisk(dev); - if (gp) - return gp->part[minor(dev)].start_sect; - return 0; -} - -EXPORT_SYMBOL(get_start_sect); - -unsigned long -get_nr_sects(kdev_t dev) -{ - struct gendisk *gp; - - gp = get_gendisk(dev); - if (gp) - return gp->part[minor(dev)].nr_sects; - return 0; -} - #ifdef CONFIG_PROC_FS /* iterator */ static void *part_start(struct seq_file *part, loff_t *pos) @@ -209,7 +184,6 @@ { rwlock_init(&gendisk_lock); blk_dev_init(); - sti(); #ifdef CONFIG_I2O i2o_init(); #endif diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Wed Jul 24 14:03:36 2002 +++ b/drivers/block/ll_rw_blk.c Wed Jul 24 14:03:36 2002 @@ -900,7 +900,8 @@ * 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() + * entered. Also see blk_stop_queue(). Must not be called from driver + * request function due to recursion issues. **/ void blk_start_queue(request_queue_t *q) { @@ -915,6 +916,18 @@ } /** + * __blk_stop_queue: see blk_stop_queue() + * + * Description: + * Like blk_stop_queue(), bust queue_lock must be held + **/ +void __blk_stop_queue(request_queue_t *q) +{ + blk_remove_plug(q); + set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); +} + +/** * blk_stop_queue - stop a queue * @q: The &request_queue_t in question * @@ -933,10 +946,8 @@ unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - blk_remove_plug(q); + __blk_stop_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); - - set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); } /** @@ -1573,16 +1584,10 @@ static inline void blk_partition_remap(struct bio *bio) { struct block_device *bdev = bio->bi_bdev; - struct gendisk *g; - if (bdev == bdev->bd_contains) return; - g = get_gendisk(to_kdev_t(bdev->bd_dev)); - if (!g) - BUG(); - - bio->bi_sector += g->part[minor(to_kdev_t((bdev->bd_dev)))].start_sect; + bio->bi_sector += bdev->bd_offset; bio->bi_bdev = bdev->bd_contains; /* lots of checks are possible */ } @@ -2047,9 +2052,6 @@ #if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD) hd_init(); #endif -#if defined(__i386__) /* Do we even need this? */ - outb_p(0xc, 0x3f2); -#endif return 0; }; @@ -2098,4 +2100,5 @@ EXPORT_SYMBOL(blk_start_queue); EXPORT_SYMBOL(blk_stop_queue); +EXPORT_SYMBOL(__blk_stop_queue); EXPORT_SYMBOL(blk_run_queues); diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Wed Jul 24 14:03:35 2002 +++ b/drivers/block/loop.c Wed Jul 24 14:03:35 2002 @@ -912,10 +912,6 @@ } err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)arg); break; - case BLKBSZGET: - case BLKBSZSET: - err = blk_ioctl(inode->i_bdev, cmd, arg); - break; default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } diff -Nru a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile --- a/drivers/block/paride/Makefile Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/Makefile Wed Jul 24 14:03:37 2002 @@ -5,14 +5,9 @@ # Rewritten to use lists instead of if-statements. # -export-objs := paride.o bpck6.o +export-objs := paride.o obj-$(CONFIG_PARIDE) += paride.o -obj-$(CONFIG_PARIDE_PD) += pd.o -obj-$(CONFIG_PARIDE_PCD) += pcd.o -obj-$(CONFIG_PARIDE_PF) += pf.o -obj-$(CONFIG_PARIDE_PT) += pt.o -obj-$(CONFIG_PARIDE_PG) += pg.o obj-$(CONFIG_PARIDE_ATEN) += aten.o obj-$(CONFIG_PARIDE_BPCK) += bpck.o obj-$(CONFIG_PARIDE_COMM) += comm.o @@ -20,13 +15,18 @@ obj-$(CONFIG_PARIDE_KBIC) += kbic.o obj-$(CONFIG_PARIDE_EPAT) += epat.o obj-$(CONFIG_PARIDE_EPIA) += epia.o -obj-$(CONFIG_PARIDE_FIT2) += fit2.o -obj-$(CONFIG_PARIDE_FIT3) += fit3.o obj-$(CONFIG_PARIDE_FRPW) += frpw.o obj-$(CONFIG_PARIDE_FRIQ) += friq.o +obj-$(CONFIG_PARIDE_FIT2) += fit2.o +obj-$(CONFIG_PARIDE_FIT3) += fit3.o obj-$(CONFIG_PARIDE_ON20) += on20.o obj-$(CONFIG_PARIDE_ON26) += on26.o obj-$(CONFIG_PARIDE_KTTI) += ktti.o obj-$(CONFIG_PARIDE_BPCK6) += bpck6.o +obj-$(CONFIG_PARIDE_PD) += pd.o +obj-$(CONFIG_PARIDE_PCD) += pcd.o +obj-$(CONFIG_PARIDE_PF) += pf.o +obj-$(CONFIG_PARIDE_PT) += pt.o +obj-$(CONFIG_PARIDE_PG) += pg.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/block/paride/aten.c b/drivers/block/paride/aten.c --- a/drivers/block/paride/aten.c Wed Jul 24 14:03:35 2002 +++ b/drivers/block/paride/aten.c Wed Jul 24 14:03:35 2002 @@ -18,6 +18,7 @@ #define ATEN_VERSION "1.01" #include +#include #include #include #include @@ -140,35 +141,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol aten = {"aten",0,2,2,1,1, - aten_write_regr, - aten_read_regr, - aten_write_block, - aten_read_block, - aten_connect, - aten_disconnect, - 0, - 0, - 0, - aten_log_adapter, - aten_init_proto, - aten_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &aten ) - 1; +static struct pi_protocol aten = { + .name = "aten", + .max_mode = 2, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = aten_write_regr, + .read_regr = aten_read_regr, + .write_block = aten_write_block, + .read_block = aten_read_block, + .connect = aten_connect, + .disconnect = aten_disconnect, + .log_adapter = aten_log_adapter, + .init_proto = aten_init_proto, + .release_proto = aten_release_proto, +}; + +static int __init aten_init(void) +{ + return pi_register(&aten)-1; +} + +static void __exit aten_exit(void) +{ + pi_unregister( &aten ); } -void cleanup_module(void) - -{ pi_unregister( &aten ); -} - -#endif - -/* end of aten.c */ MODULE_LICENSE("GPL"); +module_init(aten_init) +module_exit(aten_exit) diff -Nru a/drivers/block/paride/bpck.c b/drivers/block/paride/bpck.c --- a/drivers/block/paride/bpck.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/paride/bpck.c Wed Jul 24 14:03:39 2002 @@ -17,6 +17,7 @@ #define BPCK_VERSION "1.02" #include +#include #include #include #include @@ -452,34 +453,36 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol bpck = { "bpck",0,5,2,4,256, - bpck_write_regr, - bpck_read_regr, - bpck_write_block, - bpck_read_block, - bpck_connect, - bpck_disconnect, - bpck_test_port, - bpck_probe_unit, - bpck_test_proto, - bpck_log_adapter, - bpck_init_proto, - bpck_release_proto - }; - -#ifdef MODULE - -int init_module(void) - -{ return pi_register(&bpck) - 1; +static struct pi_protocol bpck = { + .name = "bpck", + .max_mode = 5, + .epp_first = 2, + .default_delay = 4, + .max_units = 255, + .write_regr = bpck_write_regr, + .read_regr = bpck_read_regr, + .write_block = bpck_write_block, + .read_block = bpck_read_block, + .connect = bpck_connect, + .disconnect = bpck_disconnect, + .test_port = bpck_test_port, + .probe_unit = bpck_probe_unit, + .test_proto = bpck_test_proto, + .log_adapter = bpck_log_adapter, + .init_proto = bpck_init_proto, + .release_proto = bpck_release_proto, +}; + +static int __init bpck_init(void) +{ + return pi_register(&bpck)-1; +} + +static void __exit bpck_exit(void) +{ + pi_unregister(&bpck); } -void cleanup_module(void) - -{ pi_unregister(&bpck); -} - -#endif - -/* end of bpck.c */ MODULE_LICENSE("GPL"); +module_init(bpck_init) +module_exit(bpck_exit) diff -Nru a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c --- a/drivers/block/paride/bpck6.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/paride/bpck6.c Wed Jul 24 14:03:38 2002 @@ -26,6 +26,7 @@ #define BACKPACK_VERSION "2.0.2" #include +#include #include #include #include @@ -252,65 +253,41 @@ kfree((void *)(pi->private)); } -struct pi_protocol bpck6 = { "bpck6", /* name for proto*/ - 0, /* index into proto table */ - 5, /* max mode =5 */ - 2, /* 2-5 use epp (need 8 ports) */ - 0, /* no delay (not used anyway) */ - 255, /* we can have units up to 255 */ - bpck6_write_regr, - bpck6_read_regr, - bpck6_write_block, - bpck6_read_block, - bpck6_connect, - bpck6_disconnect, - bpck6_test_port, - bpck6_probe_unit, - 0, - bpck6_log_adapter, - bpck6_init_proto, - bpck6_release_proto - }; - - -EXPORT_SYMBOL(bpck6_write_regr); -EXPORT_SYMBOL(bpck6_read_regr); -EXPORT_SYMBOL(bpck6_write_block); -EXPORT_SYMBOL(bpck6_read_block); -EXPORT_SYMBOL(bpck6_connect); -EXPORT_SYMBOL(bpck6_disconnect); -EXPORT_SYMBOL(bpck6_test_port); -EXPORT_SYMBOL(bpck6_probe_unit); -EXPORT_SYMBOL(bpck6_log_adapter); -EXPORT_SYMBOL(bpck6_init_proto); -EXPORT_SYMBOL(bpck6_release_proto); +static struct pi_protocol bpck6 = { + .name = "bpck6", + .max_mode = 5, + .epp_first = 2, /* 2-5 use epp (need 8 ports) */ + .max_units = 255, + .write_regr = bpck6_write_regr, + .read_regr = bpck6_read_regr, + .write_block = bpck6_write_block, + .read_block = bpck6_read_block, + .connect = bpck6_connect, + .disconnect = bpck6_disconnect, + .test_port = bpck6_test_port, + .probe_unit = bpck6_probe_unit, + .log_adapter = bpck6_log_adapter, + .init_proto = bpck6_init_proto, + .release_proto = bpck6_release_proto, +}; -/*---------------------------MODULE STUFF-----------------------*/ - -#ifdef MODULE -/*module information*/ - -static int init_module(void) +static int __init bpck6_init(void) { printk(KERN_INFO "bpck6: BACKPACK Protocol Driver V"BACKPACK_VERSION"\n"); printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n"); - if(verbose) - { printk(KERN_DEBUG "bpck6: verbose debug enabled.\n"); - } - return pi_register(&bpck6) - 1; } -void cleanup_module(void) +static void __exit bpck6_exit(void) { pi_unregister(&bpck6); } +MODULE_LICENSE("GPL"); MODULE_AUTHOR("Micro Solutions Inc."); MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE"); MODULE_PARM(verbose,"i"); - -#endif - +module_init(bpck6_init) +module_exit(bpck6_exit) diff -Nru a/drivers/block/paride/comm.c b/drivers/block/paride/comm.c --- a/drivers/block/paride/comm.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/comm.c Wed Jul 24 14:03:37 2002 @@ -17,6 +17,7 @@ #define COMM_VERSION "1.01" #include +#include #include #include #include @@ -196,35 +197,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol comm = {"comm",0,5,2,1,1, - comm_write_regr, - comm_read_regr, - comm_write_block, - comm_read_block, - comm_connect, - comm_disconnect, - 0, - 0, - 0, - comm_log_adapter, - comm_init_proto, - comm_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &comm ) - 1; +static struct pi_protocol comm = { + .name = "comm", + .max_mode = 5, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = comm_write_regr, + .read_regr = comm_read_regr, + .write_block = comm_write_block, + .read_block = comm_read_block, + .connect = comm_connect, + .disconnect = comm_disconnect, + .log_adapter = comm_log_adapter, + .init_proto = comm_init_proto, + .release_proto = comm_release_proto, +}; + +static int __init comm_init(void) +{ + return pi_register(&comm)-1; +} + +static void __exit comm_exit(void) +{ + pi_unregister(&comm); } -void cleanup_module(void) - -{ pi_unregister( &comm ); -} - -#endif - -/* end of comm.c */ MODULE_LICENSE("GPL"); +module_init(comm_init) +module_exit(comm_exit) diff -Nru a/drivers/block/paride/dstr.c b/drivers/block/paride/dstr.c --- a/drivers/block/paride/dstr.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/dstr.c Wed Jul 24 14:03:37 2002 @@ -16,6 +16,7 @@ #define DSTR_VERSION "1.01" #include +#include #include #include #include @@ -211,35 +212,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol dstr = {"dstr",0,5,2,1,1, - dstr_write_regr, - dstr_read_regr, - dstr_write_block, - dstr_read_block, - dstr_connect, - dstr_disconnect, - 0, - 0, - 0, - dstr_log_adapter, - dstr_init_proto, - dstr_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &dstr ) - 1; +static struct pi_protocol dstr = { + .name = "dstr", + .max_mode = 5, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = dstr_write_regr, + .read_regr = dstr_read_regr, + .write_block = dstr_write_block, + .read_block = dstr_read_block, + .connect = dstr_connect, + .disconnect = dstr_disconnect, + .log_adapter = dstr_log_adapter, + .init_proto = dstr_init_proto, + .release_proto = dstr_release_proto, +}; + +static int __init dstr_init(void) +{ + return pi_register(&dstr)-1; +} + +static void __exit dstr_exit(void) +{ + pi_unregister(&dstr); } -void cleanup_module(void) - -{ pi_unregister( &dstr ); -} - -#endif - -/* end of dstr.c */ MODULE_LICENSE("GPL"); +module_init(dstr_init) +module_exit(dstr_exit) diff -Nru a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c --- a/drivers/block/paride/epat.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/paride/epat.c Wed Jul 24 14:03:39 2002 @@ -19,6 +19,7 @@ #define EPAT_VERSION "1.02" #include +#include #include #include #include @@ -311,35 +312,34 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol epat = {"epat",0,6,3,1,1, - epat_write_regr, - epat_read_regr, - epat_write_block, - epat_read_block, - epat_connect, - epat_disconnect, - 0, - 0, - epat_test_proto, - epat_log_adapter, - epat_init_proto, - epat_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &epat) - 1; +static struct pi_protocol epat = { + .name = "epat", + .max_mode = 6, + .epp_first = 3, + .default_delay = 1, + .max_units = 1, + .write_regr = epat_write_regr, + .read_regr = epat_read_regr, + .write_block = epat_write_block, + .read_block = epat_read_block, + .connect = epat_connect, + .disconnect = epat_disconnect, + .test_proto = epat_test_proto, + .log_adapter = epat_log_adapter, + .init_proto = epat_init_proto, + .release_proto = epat_release_proto, +}; + +static int __init epat_init(void) +{ + return pi_register(&epat)-1; +} + +static void __exit epat_exit(void) +{ + pi_unregister(&epat); } -void cleanup_module(void) - -{ pi_unregister( &epat); -} - -#endif - -/* end of epat.c */ MODULE_LICENSE("GPL"); +module_init(epat_init) +module_exit(epat_exit) diff -Nru a/drivers/block/paride/epia.c b/drivers/block/paride/epia.c --- a/drivers/block/paride/epia.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/epia.c Wed Jul 24 14:03:37 2002 @@ -20,6 +20,7 @@ #define EPIA_VERSION "1.02" #include +#include #include #include #include @@ -293,36 +294,34 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol epia = {"epia",0,6,3,1,1, - epia_write_regr, - epia_read_regr, - epia_write_block, - epia_read_block, - epia_connect, - epia_disconnect, - 0, - 0, - epia_test_proto, - epia_log_adapter, - epia_init_proto, - epia_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &epia ) - 1; +static struct pi_protocol epia = { + .name = "epia", + .max_mode = 6, + .epp_first = 3, + .default_delay = 1, + .max_units = 1, + .write_regr = epia_write_regr, + .read_regr = epia_read_regr, + .write_block = epia_write_block, + .read_block = epia_read_block, + .connect = epia_connect, + .disconnect = epia_disconnect, + .test_proto = epia_test_proto, + .log_adapter = epia_log_adapter, + .init_proto = epia_init_proto, + .release_proto = epia_release_proto, +}; + +static int __init epia_init(void) +{ + return pi_register(&epia)-1; } -void cleanup_module(void) - -{ pi_unregister( &epia ); +static void __exit epia_exit(void) +{ + pi_unregister(&epia); } -#endif - -/* end of epia.c */ - MODULE_LICENSE("GPL"); +module_init(epia_init) +module_exit(epia_exit) diff -Nru a/drivers/block/paride/fit2.c b/drivers/block/paride/fit2.c --- a/drivers/block/paride/fit2.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/paride/fit2.c Wed Jul 24 14:03:38 2002 @@ -16,6 +16,7 @@ #define FIT2_VERSION "1.0" #include +#include #include #include #include @@ -129,35 +130,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol fit2 = {"fit2",0,1,2,1,1, - fit2_write_regr, - fit2_read_regr, - fit2_write_block, - fit2_read_block, - fit2_connect, - fit2_disconnect, - 0, - 0, - 0, - fit2_log_adapter, - fit2_init_proto, - fit2_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &fit2 ) - 1; +static struct pi_protocol fit2 = { + .name = "fit2", + .max_mode = 1, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = fit2_write_regr, + .read_regr = fit2_read_regr, + .write_block = fit2_write_block, + .read_block = fit2_read_block, + .connect = fit2_connect, + .disconnect = fit2_disconnect, + .log_adapter = fit2_log_adapter, + .init_proto = fit2_init_proto, + .release_proto = fit2_release_proto, +}; + +static int __init fit2_init(void) +{ + return pi_register(&fit2)-1; +} + +static void __exit fit2_exit(void) +{ + pi_unregister(&fit2); } -void cleanup_module(void) - -{ pi_unregister( &fit2 ); -} - -#endif - -/* end of fit2.c */ MODULE_LICENSE("GPL"); +module_init(fit2_init) +module_exit(fit2_exit) diff -Nru a/drivers/block/paride/fit3.c b/drivers/block/paride/fit3.c --- a/drivers/block/paride/fit3.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/fit3.c Wed Jul 24 14:03:37 2002 @@ -20,6 +20,7 @@ #define FIT3_VERSION "1.0" #include +#include #include #include #include @@ -189,35 +190,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol fit3 = {"fit3",0,3,2,1,1, - fit3_write_regr, - fit3_read_regr, - fit3_write_block, - fit3_read_block, - fit3_connect, - fit3_disconnect, - 0, - 0, - 0, - fit3_log_adapter, - fit3_init_proto, - fit3_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &fit3 ) - 1; +static struct pi_protocol fit3 = { + .name = "fit3", + .max_mode = 3, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = fit3_write_regr, + .read_regr = fit3_read_regr, + .write_block = fit3_write_block, + .read_block = fit3_read_block, + .connect = fit3_connect, + .disconnect = fit3_disconnect, + .log_adapter = fit3_log_adapter, + .init_proto = fit3_init_proto, + .release_proto = fit3_release_proto, +}; + +static int __init fit3_init(void) +{ + return pi_register(&fit3)-1; +} + +static void __exit fit3_exit(void) +{ + pi_unregister(&fit3); } -void cleanup_module(void) - -{ pi_unregister( &fit3 ); -} - -#endif - -/* end of fit3.c */ MODULE_LICENSE("GPL"); +module_init(fit3_init) +module_exit(fit3_exit) diff -Nru a/drivers/block/paride/friq.c b/drivers/block/paride/friq.c --- a/drivers/block/paride/friq.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/paride/friq.c Wed Jul 24 14:03:39 2002 @@ -28,6 +28,7 @@ #define FRIQ_VERSION "1.01" #include +#include #include #include #include @@ -250,35 +251,34 @@ MOD_DEC_USE_COUNT; } -struct pi_protocol friq = {"friq",0,5,2,1,1, - friq_write_regr, - friq_read_regr, - friq_write_block, - friq_read_block, - friq_connect, - friq_disconnect, - 0, - 0, - friq_test_proto, - friq_log_adapter, - friq_init_proto, - friq_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &friq ) - 1; +static struct pi_protocol friq = { + .name = "friq", + .max_mode = 5, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = friq_write_regr, + .read_regr = friq_read_regr, + .write_block = friq_write_block, + .read_block = friq_read_block, + .connect = friq_connect, + .disconnect = friq_disconnect, + .test_proto = friq_test_proto, + .log_adapter = friq_log_adapter, + .init_proto = friq_init_proto, + .release_proto = friq_release_proto, +}; + +static int __init friq_init(void) +{ + return pi_register(&friq)-1; +} + +static void __exit friq_exit(void) +{ + pi_unregister(&friq); } -void cleanup_module(void) - -{ pi_unregister( &friq ); -} - -#endif - -/* end of friq.c */ MODULE_LICENSE("GPL"); +module_init(friq_init) +module_exit(friq_exit) diff -Nru a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c --- a/drivers/block/paride/frpw.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/paride/frpw.c Wed Jul 24 14:03:39 2002 @@ -26,6 +26,7 @@ #define FRPW_VERSION "1.03" #include +#include #include #include #include @@ -291,35 +292,34 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol frpw = {"frpw",0,6,2,2,1, - frpw_write_regr, - frpw_read_regr, - frpw_write_block, - frpw_read_block, - frpw_connect, - frpw_disconnect, - 0, - 0, - frpw_test_proto, - frpw_log_adapter, - frpw_init_proto, - frpw_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &frpw ) - 1; +static struct pi_protocol frpw = { + .name = "frpw", + .max_mode = 6, + .epp_first = 2, + .default_delay = 2, + .max_units = 1, + .write_regr = frpw_write_regr, + .read_regr = frpw_read_regr, + .write_block = frpw_write_block, + .read_block = frpw_read_block, + .connect = frpw_connect, + .disconnect = frpw_disconnect, + .test_proto = frpw_test_proto, + .log_adapter = frpw_log_adapter, + .init_proto = frpw_init_proto, + .release_proto = frpw_release_proto, +}; + +static int __init frpw_init(void) +{ + return pi_register(&frpw)-1; +} + +static void __exit frpw_exit(void) +{ + pi_unregister(&frpw); } -void cleanup_module(void) - -{ pi_unregister( &frpw ); -} - -#endif - -/* end of frpw.c */ MODULE_LICENSE("GPL"); +module_init(frpw_init) +module_exit(frpw_exit) diff -Nru a/drivers/block/paride/kbic.c b/drivers/block/paride/kbic.c --- a/drivers/block/paride/kbic.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/paride/kbic.c Wed Jul 24 14:03:39 2002 @@ -21,6 +21,7 @@ #define KBIC_VERSION "1.01" #include +#include #include #include #include @@ -258,56 +259,51 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol k951 = {"k951",0,6,3,1,1, - kbic_write_regr, - kbic_read_regr, - kbic_write_block, - kbic_read_block, - k951_connect, - k951_disconnect, - 0, - 0, - 0, - k951_log_adapter, - kbic_init_proto, - kbic_release_proto - }; - - -struct pi_protocol k971 = {"k971",0,6,3,1,1, - kbic_write_regr, - kbic_read_regr, - kbic_write_block, - kbic_read_block, - k971_connect, - k971_disconnect, - 0, - 0, - 0, - k971_log_adapter, - kbic_init_proto, - kbic_release_proto - }; - -#ifdef MODULE - -int init_module(void) - -{ int s5,s7; - - s5 = pi_register(&k951); - s7 = pi_register(&k971); - - return (s5 || s7) - 1; -} - -void cleanup_module(void) - -{ pi_unregister( &k951 ); - pi_unregister( &k971 ); +static struct pi_protocol k951 = { + .name = "k951", + .max_mode = 6, + .epp_first = 3, + .default_delay = 1, + .max_units = 1, + .write_regr = kbic_write_regr, + .read_regr = kbic_read_regr, + .write_block = kbic_write_block, + .read_block = kbic_read_block, + .connect = k951_connect, + .disconnect = k951_disconnect, + .log_adapter = k951_log_adapter, + .init_proto = kbic_init_proto, + .release_proto = kbic_release_proto +}; + +static struct pi_protocol k971 = { + .name = "k971", + .max_mode = 6, + .epp_first = 3, + .default_delay = 1, + .max_units = 1, + .write_regr = kbic_write_regr, + .read_regr = kbic_read_regr, + .write_block = kbic_write_block, + .read_block = kbic_read_block, + .connect = k971_connect, + .disconnect = k971_disconnect, + .log_adapter = k971_log_adapter, + .init_proto = kbic_init_proto, + .release_proto = kbic_release_proto +}; + +static int __init kbic_init(void) +{ + return (pi_register(&k951)||pi_register(&k971))-1; +} + +static void __exit kbic_exit(void) +{ + pi_unregister(&k951); + pi_unregister(&k971); } -#endif - -/* end of kbic.c */ MODULE_LICENSE("GPL"); +module_init(kbic_init) +module_exit(kbic_exit) diff -Nru a/drivers/block/paride/ktti.c b/drivers/block/paride/ktti.c --- a/drivers/block/paride/ktti.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/ktti.c Wed Jul 24 14:03:37 2002 @@ -12,6 +12,7 @@ #define KTTI_VERSION "1.0" #include +#include #include #include #include @@ -106,35 +107,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol ktti = {"ktti",0,1,2,1,1, - ktti_write_regr, - ktti_read_regr, - ktti_write_block, - ktti_read_block, - ktti_connect, - ktti_disconnect, - 0, - 0, - 0, - ktti_log_adapter, - ktti_init_proto, - ktti_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &ktti ) - 1; +static struct pi_protocol ktti = { + .name = "ktti", + .max_mode = 1, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = ktti_write_regr, + .read_regr = ktti_read_regr, + .write_block = ktti_write_block, + .read_block = ktti_read_block, + .connect = ktti_connect, + .disconnect = ktti_disconnect, + .log_adapter = ktti_log_adapter, + .init_proto = ktti_init_proto, + .release_proto = ktti_release_proto, +}; + +static int __init ktti_init(void) +{ + return pi_register(&ktti)-1; +} + +static void __exit ktti_exit(void) +{ + pi_unregister(&ktti); } -void cleanup_module(void) - -{ pi_unregister( &ktti ); -} - -#endif - -/* end of ktti.c */ MODULE_LICENSE("GPL"); +module_init(ktti_init) +module_exit(ktti_exit) diff -Nru a/drivers/block/paride/on20.c b/drivers/block/paride/on20.c --- a/drivers/block/paride/on20.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/on20.c Wed Jul 24 14:03:37 2002 @@ -15,6 +15,7 @@ #define ON20_VERSION "1.01" #include +#include #include #include #include @@ -131,35 +132,33 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol on20 = {"on20",0,2,2,1,1, - on20_write_regr, - on20_read_regr, - on20_write_block, - on20_read_block, - on20_connect, - on20_disconnect, - 0, - 0, - 0, - on20_log_adapter, - on20_init_proto, - on20_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &on20 ) - 1; +static struct pi_protocol on20 = { + .name = "on20", + .max_mode = 2, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = on20_write_regr, + .read_regr = on20_read_regr, + .write_block = on20_write_block, + .read_block = on20_read_block, + .connect = on20_connect, + .disconnect = on20_disconnect, + .log_adapter = on20_log_adapter, + .init_proto = on20_init_proto, + .release_proto = on20_release_proto, +}; + +static int __init on20_init(void) +{ + return pi_register(&on20)-1; +} + +static void __exit on20_exit(void) +{ + pi_unregister(&on20); } -void cleanup_module(void) - -{ pi_unregister( &on20 ); -} - -#endif - -/* end of on20.c */ MODULE_LICENSE("GPL"); +module_init(on20_init) +module_exit(on20_exit) diff -Nru a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c --- a/drivers/block/paride/on26.c Wed Jul 24 14:03:37 2002 +++ b/drivers/block/paride/on26.c Wed Jul 24 14:03:37 2002 @@ -19,6 +19,7 @@ #define ON26_VERSION "1.04" #include +#include #include #include #include @@ -296,36 +297,34 @@ { MOD_DEC_USE_COUNT; } -struct pi_protocol on26 = {"on26",0,5,2,1,1, - on26_write_regr, - on26_read_regr, - on26_write_block, - on26_read_block, - on26_connect, - on26_disconnect, - on26_test_port, - 0, - 0, - on26_log_adapter, - on26_init_proto, - on26_release_proto - }; - - -#ifdef MODULE - -int init_module(void) - -{ return pi_register( &on26 ) - 1; +static struct pi_protocol on26 = { + .name = "on26", + .max_mode = 5, + .epp_first = 2, + .default_delay = 1, + .max_units = 1, + .write_regr = on26_write_regr, + .read_regr = on26_read_regr, + .write_block = on26_write_block, + .read_block = on26_read_block, + .connect = on26_connect, + .disconnect = on26_disconnect, + .test_port = on26_test_port, + .log_adapter = on26_log_adapter, + .init_proto = on26_init_proto, + .release_proto = on26_release_proto, +}; + +static int __init on26_init(void) +{ + return pi_register(&on26)-1; } -void cleanup_module(void) - -{ pi_unregister( &on26 ); +static void __exit on26_exit(void) +{ + pi_unregister(&on26); } -#endif - -/* end of on26.c */ - MODULE_LICENSE("GPL"); +module_init(on26_init) +module_exit(on26_exit) diff -Nru a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c --- a/drivers/block/paride/paride.c Wed Jul 24 14:03:36 2002 +++ b/drivers/block/paride/paride.c Wed Jul 24 14:03:36 2002 @@ -431,136 +431,3 @@ } EXPORT_SYMBOL(pi_init); - -#ifdef MODULE - -int init_module(void) - -{ - int k; - const char *indicate_pp = ""; -#ifdef CONFIG_PARPORT - indicate_pp = " (parport)"; -#endif - - for (k=0;k +#include #include #include #include @@ -200,9 +201,6 @@ #define IDE_READY 0x40 #define IDE_BUSY 0x80 -int pcd_init(void); -void cleanup_module( void ); - static int pcd_open(struct cdrom_device_info *cdi, int purpose); static void pcd_release(struct cdrom_device_info *cdi); static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); @@ -327,84 +325,18 @@ } } -int pcd_init (void) /* preliminary initialisation */ -{ - int unit; - - if (disable) return -1; - - pcd_init_units(); - - if (pcd_detect()) return -1; - - /* get the atapi capabilities page */ - pcd_probe_capabilities(); - - if (register_blkdev(MAJOR_NR,name,&pcd_bdops)) { - printk("pcd: unable to get major number %d\n",MAJOR_NR); - return -1; - } - - for (unit=0;unitdev); - - if ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV; - +{ + int unit = DEVICE_NR(cdi->dev); + if ((unit >= PCD_UNITS) || (!PCD.present)) + return -ENODEV; return 0; } static void pcd_release(struct cdrom_device_info *cdi) - { } -#ifdef MODULE - -/* Glue for modules ... */ - -int init_module(void) - -{ int err; - -#ifdef PARIDE_JUMBO - { extern paride_init(); - paride_init(); - } -#endif - - err = pcd_init(); - - return err; -} - -void cleanup_module(void) - -{ int unit; - - for (unit=0;unit #include -#include #include -#include -#include #include -#include #include #include /* for the eject ioctl */ -#include #include @@ -181,8 +177,8 @@ {"nice",1,&nice}}; void pd_setup( char *str, int *ints) - -{ generic_setup(pd_stt,7,str); +{ + generic_setup(pd_stt,7,str); } #endif @@ -199,19 +195,15 @@ #include "paride.h" -#define PD_BITS 4 - -/* set up defines for blk.h, why don't all drivers do it this way ? */ - #define MAJOR_NR major -#define DEVICE_NR(device) (minor(device)>>PD_BITS) -#define DEVICE_OFF(device) #include #include #include "pseudo.h" +#define PD_BITS 4 +#define DEVICE_NR(device) (minor(device)>>PD_BITS) #define PD_PARTNS (1<i_rdev); -{ int unit = DEVICE_NR(inode->i_rdev); - - if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV; - - wait_event (pd_wait_open, pd_valid); + if ((unit >= PD_UNITS) || (!PD.present)) + return -ENODEV; PD.access++; @@ -434,11 +387,8 @@ unsigned int cmd, unsigned long arg) { struct hd_geometry *geo = (struct hd_geometry *) arg; - int err, unit; + int err, unit = DEVICE_NR(inode->i_rdev); - if (!inode || kdev_none(inode->i_rdev)) - return -EINVAL; - unit = DEVICE_NR(inode->i_rdev); if (!PD.present) return -ENODEV; @@ -461,50 +411,34 @@ put_user(PD.heads, (char *) &geo->heads); put_user(PD.sectors, (char *) &geo->sectors); } - put_user(get_start_sect(inode->i_rdev), (long *)&geo->start); + put_user(get_start_sect(inode->i_bdev), (long *)&geo->start); return 0; case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; return pd_revalidate(inode->i_rdev); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); default: return -EINVAL; } } static int pd_release (struct inode *inode, struct file *file) +{ + int unit = DEVICE_NR(inode->i_rdev); -{ kdev_t devp; - int unit; - - devp = inode->i_rdev; - unit = DEVICE_NR(devp); - - if ((unit >= PD_UNITS) || (PD.access <= 0)) - return -EINVAL; - - PD.access--; - - if (!PD.access && PD.removable) + if (!--PD.access && PD.removable) pd_doorlock(unit,IDE_DOORUNLOCK); return 0; } static int pd_check_media( kdev_t dev) - -{ int r, unit; - - unit = DEVICE_NR(dev); - if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV; - if (!PD.removable) return 0; +{ + int r, unit = DEVICE_NR(dev); + if ((unit >= PD_UNITS) || (!PD.present)) + return -ENODEV; + if (!PD.removable) + return 0; pd_media_check(unit); r = PD.changed; PD.changed = 0; @@ -513,64 +447,26 @@ static int pd_revalidate(kdev_t dev) { - int unit, res; - long flags; + int unit = DEVICE_NR(dev); + kdev_t device = mk_kdev(MAJOR_NR, unit << PD_BITS); + int res; - unit = DEVICE_NR(dev); if ((unit >= PD_UNITS) || !PD.present) return -ENODEV; - save_flags(flags); - cli(); - if (PD.access > 1) { - restore_flags(flags); - return -EBUSY; - } - pd_valid = 0; - restore_flags(flags); - - res = wipe_partitions(dev); + res = dev_lock_part(device); + if (res < 0) + return res; + res = wipe_partitions(device); if (res == 0 && pd_identify(unit)) - grok_partitions(dev, PD.capacity); + grok_partitions(device, PD.capacity); - pd_valid = 1; - wake_up(&pd_wait_open); + dev_unlock_part(device); return res; } -#ifdef MODULE - -/* Glue for modules ... */ - -void cleanup_module(void); - -int init_module(void) - -{ - -#ifdef PARIDE_JUMBO - { extern paride_init(); - paride_init(); - } -#endif - return pd_init(); -} - -void cleanup_module(void) -{ - int unit; - - devfs_unregister_blkdev(MAJOR_NR, name); - del_gendisk(&pd_gendisk); - - for (unit=0; unit>= 8) & 255; + c1 = (block >>= 8) & 255; + h = ((block >>= 8) & 15) + 0x40; + } else { + s = ( block % PD.sectors) + 1; + h = ( block /= PD.sectors) % PD.heads; + c0 = ( block /= PD.heads) % 256; + c1 = (block >>= 8); + } pd_send_command(unit,count,s,h,c0,c1,func); } @@ -742,10 +641,14 @@ } pi_read_block(PI,pd_scratch,512); pi_disconnect(PI); - PD.sectors = word_val(6); - PD.heads = word_val(3); - PD.cylinders = word_val(1); - PD.capacity = PD.sectors*PD.heads*PD.cylinders; + PD.can_lba = pd_scratch[99] & 2; + PD.sectors = le16_to_cpu(*(u16*)(pd_scratch+12)); + PD.heads = le16_to_cpu(*(u16*)(pd_scratch+6)); + PD.cylinders = le16_to_cpu(*(u16*)(pd_scratch+2)); + if (PD.can_lba) + PD.capacity = le32_to_cpu(*(u32*)(pd_scratch + 120)); + else + PD.capacity = PD.sectors*PD.heads*PD.cylinders; for(j=0;j -#include +#include #include -#include #include -#include #include #include #include @@ -240,7 +238,6 @@ #define ATAPI_READ_10 0x28 #define ATAPI_WRITE_10 0x2a -int pf_init(void); #ifdef MODULE void cleanup_module( void ); #endif @@ -337,34 +334,6 @@ } } -int pf_init (void) /* preliminary initialisation */ - -{ int i; - request_queue_t * q; - - if (disable) return -1; - - pf_init_units(); - - if (pf_detect()) return -1; - pf_busy = 0; - - if (register_blkdev(MAJOR_NR,name,&pf_fops)) { - printk("pf_init: unable to get major number %d\n", - major); - return -1; - } - q = BLK_DEFAULT_QUEUE(MAJOR_NR); - blk_init_queue(q, do_pf_request, &pf_spin_lock); - blk_queue_max_phys_segments(q, cluster); - blk_queue_max_hw_segments(q, cluster); - - for (i=0;ii_rdev); @@ -423,10 +392,6 @@ return put_user(PF.capacity,(long *) arg); case BLKGETSIZE64: return put_user((u64)PF.capacity << 9,(u64 *)arg); - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - return blk_ioctl(inode->i_bdev, cmd, arg); default: return -EINVAL; } @@ -458,39 +423,6 @@ { return 1; } -#ifdef MODULE - -/* Glue for modules ... */ - -void cleanup_module(void); - -int init_module(void) - -{ int err; - -#ifdef PARIDE_JUMBO - { extern paride_init(); - paride_init(); - } -#endif - - err = pf_init(); - - return err; -} - -void cleanup_module(void) - -{ int unit; - - unregister_blkdev(MAJOR_NR,name); - - for (unit=0;unit -#include +#include #include #include -#include #include #include #include #include -#include -#include #include @@ -218,11 +215,6 @@ #define ATAPI_IDENTIFY 0x12 -int pg_init(void); -#ifdef MODULE -void cleanup_module( void ); -#endif - static int pg_open(struct inode *inode, struct file *file); static int pg_release (struct inode *inode, struct file *file); static ssize_t pg_read(struct file * filp, char * buf, @@ -291,64 +283,6 @@ static devfs_handle_t devfs_handle; -int pg_init (void) /* preliminary initialisation */ - -{ int unit; - - if (disable) return -1; - - pg_init_units(); - - if (pg_detect()) return -1; - - if (devfs_register_chrdev(major,name,&pg_fops)) { - printk("pg_init: unable to get major number %d\n", - major); - for (unit=0;unit -#include +#include #include #include -#include #include #include #include -#include -#include #include @@ -209,11 +206,6 @@ #define ATAPI_MODE_SENSE 0x1a #define ATAPI_LOG_SENSE 0x4d -int pt_init(void); -#ifdef MODULE -void cleanup_module( void ); -#endif - static int pt_open(struct inode *inode, struct file *file); static int pt_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg); @@ -291,71 +283,9 @@ PT.name[j] = 0; if (DU[D_PRT]) pt_drive_count++; } -} - -static devfs_handle_t devfs_handle; - -int pt_init (void) /* preliminary initialisation */ - -{ int unit; - - if (disable) return -1; - - pt_init_units(); - - if (pt_detect()) return -1; - - if (devfs_register_chrdev(major,name,&pt_fops)) { - printk("pt_init: unable to get major number %d\n", - major); - for (unit=0;uniti_rdev); - - if (dev < ps2esdi_drives) { - while (!ps2esdi_valid[dev]) - sleep_on(&ps2esdi_wait_open); - - access_count[dev]++; - - return (0); - } else - return (-ENODEV); -} - - - -static int ps2esdi_release(struct inode *inode, struct file *file) -{ - int dev = DEVICE_NR(inode->i_rdev); - - if (dev < ps2esdi_drives) { - access_count[dev]--; - } + if (dev >= ps2esdi_drives) + return -ENODEV; return 0; } - - static int ps2esdi_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { @@ -1125,7 +1096,7 @@ put_user(ps2esdi_info[dev].head, (char *) &geometry->heads); put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors); put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders); - put_user(get_start_sect(inode->i_rdev), + put_user(get_start_sect(inode->b_rdev), (long *) &geometry->start); return 0; @@ -1136,16 +1107,6 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; return (ps2esdi_reread_partitions(inode->i_rdev)); - - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKBSZGET: - case BLKBSZSET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); } return (-EINVAL); } @@ -1155,24 +1116,20 @@ static int ps2esdi_reread_partitions(kdev_t dev) { int target = DEVICE_NR(dev); - int res; + kdev_t device = mk_kdev(MAJOR_NR, target << 6); + int res = dev_lock_part(device); - cli(); - ps2esdi_valid[target] = (access_count[target] != 1); - sti(); - if (ps2esdi_valid[target]) - return (-EBUSY); + if (res < 0) + return res; - res = wipe_partitions(dev); + res = wipe_partitions(device); if (res == 0) - grok_partitions(dev, ps2esdi_info[target].head + grok_partitions(device, ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect); - ps2esdi_valid[target] = 1; - wake_up(&ps2esdi_wait_open); - - return (res); + dev_unlock_part(device); + return res; } static void ps2esdi_reset_timer(unsigned long unused) diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Wed Jul 24 14:03:38 2002 +++ b/drivers/block/rd.c Wed Jul 24 14:03:38 2002 @@ -303,12 +303,6 @@ } up(&inode->i_bdev->bd_sem); break; - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - error = blk_ioctl(inode->i_bdev, cmd, arg); } out: return error; diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Wed Jul 24 14:03:39 2002 +++ b/drivers/block/umem.c Wed Jul 24 14:03:39 2002 @@ -65,7 +65,7 @@ #define MM_BLKSIZE 1024 /* 1k blocks */ #define MM_HARDSECT 512 /* 512-byte hardware sectors */ #define MM_SHIFT 6 /* max 64 partitions on 4 cards */ -#define DEVICE_NR(device) (MINOR(device)>>MM_SHIFT) +#define DEVICE_NR(device) (minor(device)>>MM_SHIFT) /* * Version Information @@ -150,7 +150,6 @@ unsigned long last_change; } battery[2]; - atomic_t usage; spinlock_t lock; int check_batteries; @@ -813,31 +812,21 @@ * Note no locks taken out here. In a worst case scenario, we could drop * a chunk of system memory. But that should never happen, since validation * happens at open or mount time, when locks are held. + * + * That's crap, since doing that while some partitions are opened + * or mounted will give you really nasty results. */ static int mm_revalidate(kdev_t i_rdev) { - int i; - - int card_number = DEVICE_NR(kdev_val(i_rdev)); - /* first partition, # of partitions */ - int part1 = (card_number << MM_SHIFT) + 1; - int npart = (1 << MM_SHIFT) -1; - - /* first clear old partition information */ - for (i=0; ii_rdev)); @@ -883,16 +862,15 @@ size = cards[card_number].mm_size * (1024 / MM_HARDSECT); geo.heads = 64; geo.sectors = 32; - geo.start = mm_gendisk.part[minor].start_sect; + geo.start = get_start_sect(inode->i_bdev); geo.cylinders = size / (geo.heads * geo.sectors); if (copy_to_user((void *) arg, &geo, sizeof(geo))) return -EFAULT; return 0; - default: - return blk_ioctl(i->i_bdev, cmd, arg); + return -EINVAL; } return -ENOTTY; /* unknown command */ @@ -905,7 +883,7 @@ */ static int mm_check_change(kdev_t i_rdev) { - int card_number = DEVICE_NR(kdev_val(i_rdev)); + int card_number = DEVICE_NR(i_rdev); /* struct cardinfo *dev = cards + card_number; */ if (card_number >= num_cards) /* paranoid */ return 0; @@ -920,38 +898,8 @@ */ static int mm_open(struct inode *i, struct file *filp) { - int num; - struct cardinfo *card; - - num = DEVICE_NR(kdev_val(i->i_rdev)); - if (num >= num_cards) + if (DEVICE_NR(i->i_rdev) >= num_cards) return -ENXIO; - - card = cards + num; - - atomic_inc(&card->usage); - MOD_INC_USE_COUNT; - - return 0; -} -/* ------------------------------------------------------------------------------------ --- mm_do_release ------------------------------------------------------------------------------------ -*/ -static int mm_do_release(struct inode *i, struct file *filp) -{ - int num; - struct cardinfo *card; - - num = DEVICE_NR(kdev_val(i->i_rdev)); - - card = cards + num; - - if (atomic_dec_and_test(&card->usage)) - invalidate_device(i->i_rdev, 1); - - MOD_DEC_USE_COUNT; return 0; } /* @@ -962,7 +910,6 @@ static struct block_device_operations mm_fops = { owner: THIS_MODULE, open: mm_open, - release: mm_do_release, ioctl: mm_ioctl, revalidate: mm_revalidate, check_media_change: mm_check_change, @@ -1243,7 +1190,7 @@ static request_queue_t * mm_queue_proc(kdev_t dev) { - int c = DEVICE_NR(kdev_val(dev)); + int c = DEVICE_NR(dev); if (c < MM_MAXCARDS) return &cards[c].queue; @@ -1293,7 +1240,6 @@ blk_dev[MAJOR_NR].queue = mm_queue_proc; add_gendisk(&mm_gendisk); - blk_size[MAJOR_NR] = mm_gendisk.sizes; for (i = 0; i < num_cards; i++) { register_disk(&mm_gendisk, mk_kdev(MAJOR_NR, i<i_rdev); - - if (dev < xd_drives) { - while (!xd_valid[dev]) - sleep_on(&xd_wait_open); - - xd_access[dev]++; - - return (0); - } - - return -ENXIO; + if (dev >= xd_drives) + return -ENXIO; + return 0; } /* do_xd_request: handle an incoming request */ @@ -329,7 +315,7 @@ g.heads = xd_info[dev].heads; g.sectors = xd_info[dev].sectors; g.cylinders = xd_info[dev].cylinders; - g.start = get_start_sect(inode->i_rdev); + g.start = get_start_sect(inode->i_bdev); return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0; } case HDIO_SET_DMA: @@ -351,50 +337,28 @@ return -EACCES; return xd_reread_partitions(inode->i_rdev); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKROSET: - case BLKROGET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; } } -/* xd_release: release the device */ -static int xd_release (struct inode *inode, struct file *file) -{ - int target = DEVICE_NR(inode->i_rdev); - if (target < xd_drives) - xd_access[target]--; - return 0; -} - /* xd_reread_partitions: rereads the partition table from a drive */ static int xd_reread_partitions(kdev_t dev) { - int target; - int res; + int target = DEVICE_NR(dev); + kdev_t device = mk_kdev(MAJOR_NR, target << 6); + int res = dev_lock_part(device); - target = DEVICE_NR(dev); - - cli(); - xd_valid[target] = (xd_access[target] != 1); - sti(); - if (xd_valid[target]) - return -EBUSY; + if (res < 0) + return 0; - res = wipe_partitions(dev); + res = wipe_partitions(device); if (!res) - grok_partitions(dev, xd_info[target].heads + grok_partitions(device, xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors); - xd_valid[target] = 1; - wake_up(&xd_wait_open); + dev_unlock_part(device); return res; } diff -Nru a/drivers/block/xd.h b/drivers/block/xd.h --- a/drivers/block/xd.h Wed Jul 24 14:03:37 2002 +++ b/drivers/block/xd.h Wed Jul 24 14:03:37 2002 @@ -113,7 +113,6 @@ static int xd_open (struct inode *inode,struct file *file); static void do_xd_request (request_queue_t * q); static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg); -static int xd_release (struct inode *inode,struct file *file); static int xd_reread_partitions (kdev_t dev); static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count); static void xd_recalibrate (u_char drive); diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c Wed Jul 24 14:03:36 2002 +++ b/drivers/cdrom/cdrom.c Wed Jul 24 14:03:36 2002 @@ -1732,11 +1732,6 @@ because they fill up the sys log when CD players poll the drive. */ switch (cmd) { - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKSSZGET: - return blk_ioctl(ip->i_bdev, cmd, arg); case CDROMSUBCHNL: { struct cdrom_subchnl q; u_char requested, back; diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in --- a/drivers/char/Config.in Wed Jul 24 14:03:36 2002 +++ b/drivers/char/Config.in Wed Jul 24 14:03:36 2002 @@ -8,25 +8,6 @@ if [ "$CONFIG_VT" = "y" ]; then bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE fi -tristate 'Standard/generic (8250/16550 and compatible UARTs) serial support' CONFIG_SERIAL -if [ "$CONFIG_SERIAL" = "y" ]; then - bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE - if [ "$CONFIG_ARCH_ACORN" = "y" ]; then - tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL - tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL - fi -fi -if [ "$CONFIG_ACPI" = "y" -a "$CONFIG_IA64" = "y" ]; then - bool ' Support for serial ports defined by ACPI tables' CONFIG_SERIAL_ACPI -fi -dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL -if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then - bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS - bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ - bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_DETECT_IRQ - bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT - bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6 -fi bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then tristate ' Computone IntelliPort Plus serial support' CONFIG_COMPUTONE @@ -85,15 +66,9 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232 fi -if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then - bool 'DC21285 serial port support' CONFIG_SERIAL_21285 - if [ "$CONFIG_SERIAL_21285" = "y" ]; then - if [ "$CONFIG_OBSOLETE" = "y" ]; then - bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD - fi - bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE - fi -fi + +source drivers/serial/Config.in + bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Wed Jul 24 14:03:39 2002 +++ b/drivers/char/Makefile Wed Jul 24 14:03:39 2002 @@ -13,20 +13,18 @@ # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. export-objs := busmouse.o console.o keyboard.o sysrq.o \ - misc.o pty.o random.o selection.o serial.o \ + misc.o pty.o random.o selection.o \ sonypi.o tty_io.o tty_ioctl.o generic_serial.o rtc.o \ ip2main.o KEYMAP =defkeymap.o KEYBD =pc_keyb.o CONSOLE =console.o -SERIAL =serial.o ifeq ($(ARCH),s390) KEYMAP = KEYBD = CONSOLE = - SERIAL = endif ifeq ($(ARCH),mips) @@ -39,7 +37,6 @@ KEYMAP = KEYBD = CONSOLE = - SERIAL = endif ifeq ($(ARCH),m68k) @@ -48,7 +45,15 @@ else KEYBD = endif - SERIAL = +endif + +ifdef CONFIG_Q40 + KEYBD += q40_keyb.o + SERIAL = serial.o +endif + +ifdef CONFIG_APOLLO + KEYBD += dn_keyb.o endif ifeq ($(ARCH),arm) @@ -96,15 +101,6 @@ ifeq ($(CONFIG_BAGET_MIPS),y) KEYBD = - SERIAL = -endif - -ifeq ($(CONFIG_NINO),y) - SERIAL = -endif - -ifneq ($(CONFIG_SUN_SERIAL),) - SERIAL = endif ifeq ($(CONFIG_QTRONIX_KEYBOARD),y) @@ -113,11 +109,7 @@ endif obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o -obj-$(CONFIG_SERIAL) += $(SERIAL) -obj-$(CONFIG_SERIAL_ACPI) += acpi_serial.o -obj-$(CONFIG_SERIAL_21285) += serial_21285.o -obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o -obj-$(CONFIG_SERIAL_AMBA) += serial_amba.o +#obj-$(CONFIG_SERIAL) += $(SERIAL) # Fix for decserial.o ifndef CONFIG_SUN_KEYBOARD obj-$(CONFIG_VT) += keyboard.o $(KEYMAP) $(KEYBD) diff -Nru a/drivers/char/acpi_serial.c b/drivers/char/acpi_serial.c --- a/drivers/char/acpi_serial.c Wed Jul 24 14:03:36 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,203 +0,0 @@ -/* - * linux/drivers/char/acpi_serial.c - * - * Copyright (C) 2000 Hewlett-Packard Co. - * Copyright (C) 2000 Khalid Aziz - * - * Detect and initialize the headless console serial port defined in - * SPCR table and debug serial port defined in DBGP table - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/*#include */ - -#undef SERIAL_DEBUG_ACPI - -/* - * Query ACPI tables for a debug and a headless console serial - * port. If found, add them to rs_table[]. A pointer to either SPCR - * or DBGP table is passed as parameter. This function should be called - * before serial_console_init() is called to make sure the SPCR serial - * console will be available for use. IA-64 kernel calls this function - * from within acpi.c when it encounters SPCR or DBGP tables as it parses - * the ACPI 2.0 tables during bootup. - * - */ -void __init setup_serial_acpi(void *tablep) -{ - acpi_ser_t *acpi_ser_p; - struct serial_struct serial_req; - unsigned long iobase; - int global_sys_irq; - -#ifdef SERIAL_DEBUG_ACPI - printk("Entering setup_serial_acpi()\n"); -#endif - - /* Now get the table */ - if (tablep == NULL) { - return; - } - - acpi_ser_p = (acpi_ser_t *)tablep; - - /* - * Perform a sanity check on the table. Table should have a - * signature of "SPCR" or "DBGP" and it should be atleast 52 bytes - * long. - */ - if ((strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE, - ACPI_SIG_LEN) != 0) && - (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE, - ACPI_SIG_LEN) != 0)) { - return; - } - if (acpi_ser_p->length < 52) { - return; - } - - iobase = (((u64) acpi_ser_p->base_addr.addrh) << 32) | acpi_ser_p->base_addr.addrl; - global_sys_irq = (acpi_ser_p->global_int[3] << 24) | - (acpi_ser_p->global_int[2] << 16) | - (acpi_ser_p->global_int[1] << 8) | - acpi_ser_p->global_int[0]; - -#ifdef SERIAL_DEBUG_ACPI - printk("setup_serial_acpi(): table pointer = 0x%p\n", acpi_ser_p); - printk(" sig = '%c%c%c%c'\n", - acpi_ser_p->signature[0], - acpi_ser_p->signature[1], - acpi_ser_p->signature[2], - acpi_ser_p->signature[3]); - printk(" length = %d\n", acpi_ser_p->length); - printk(" Rev = %d\n", acpi_ser_p->rev); - printk(" Interface type = %d\n", acpi_ser_p->intfc_type); - printk(" Base address = 0x%lX\n", iobase); - printk(" IRQ = %d\n", acpi_ser_p->irq); - printk(" Global System Int = %d\n", global_sys_irq); - printk(" Baud rate = "); - switch (acpi_ser_p->baud) { - case ACPI_SERIAL_BAUD_9600: - printk("9600\n"); - break; - - case ACPI_SERIAL_BAUD_19200: - printk("19200\n"); - break; - - case ACPI_SERIAL_BAUD_57600: - printk("57600\n"); - break; - - case ACPI_SERIAL_BAUD_115200: - printk("115200\n"); - break; - - default: - printk("Huh (%d)\n", acpi_ser_p->baud); - break; - - } - if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) { - printk(" PCI serial port:\n"); - printk(" Bus %d, Device %d, Vendor ID 0x%x, Dev ID 0x%x\n", - acpi_ser_p->pci_bus, acpi_ser_p->pci_dev, - acpi_ser_p->pci_vendor_id, acpi_ser_p->pci_dev_id); - } -#endif - - /* - * Now build a serial_req structure to update the entry in - * rs_table for the headless console port. - */ - switch (acpi_ser_p->intfc_type) { - case ACPI_SERIAL_INTFC_16550: - serial_req.type = PORT_16550; - serial_req.baud_base = BASE_BAUD; - break; - - case ACPI_SERIAL_INTFC_16450: - serial_req.type = PORT_16450; - serial_req.baud_base = BASE_BAUD; - break; - - default: - serial_req.type = PORT_UNKNOWN; - break; - } - if (strncmp(acpi_ser_p->signature, ACPI_SPCRT_SIGNATURE, - ACPI_SIG_LEN) == 0) { - serial_req.line = ACPI_SERIAL_CONSOLE_PORT; - } - else if (strncmp(acpi_ser_p->signature, ACPI_DBGPT_SIGNATURE, - ACPI_SIG_LEN) == 0) { - serial_req.line = ACPI_SERIAL_DEBUG_PORT; - } - /* - * Check if this is an I/O mapped address or a memory mapped address - */ - if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_MEM_SPACE) { - serial_req.port = 0; - serial_req.port_high = 0; - serial_req.iomem_base = (void *)ioremap(iobase, 64); - serial_req.io_type = SERIAL_IO_MEM; - } - else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_IO_SPACE) { - serial_req.port = (unsigned long) iobase & 0xffffffff; - serial_req.port_high = (unsigned long)(((u64)iobase) >> 32); - serial_req.iomem_base = NULL; - serial_req.io_type = SERIAL_IO_PORT; - } - else if (acpi_ser_p->base_addr.space_id == ACPI_SERIAL_PCICONF_SPACE) { - printk("WARNING: No support for PCI serial console\n"); - return; - } - - /* - * If the table does not have IRQ information, use 0 for IRQ. - * This will force rs_init() to probe for IRQ. - */ - if (acpi_ser_p->length < 53) { - serial_req.irq = 0; - } - else { - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_BOOT_AUTOCONF | - ASYNC_AUTO_IRQ; - if (acpi_ser_p->int_type & - (ACPI_SERIAL_INT_APIC | ACPI_SERIAL_INT_SAPIC)) { - serial_req.irq = global_sys_irq; - } - else if (acpi_ser_p->int_type & ACPI_SERIAL_INT_PCAT) { - serial_req.irq = acpi_ser_p->irq; - } - else { - /* - * IRQ type not being set would mean UART will - * run in polling mode. Do not probe for IRQ in - * that case. - */ - serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF; - } - } - - serial_req.xmit_fifo_size = serial_req.custom_divisor = 0; - serial_req.close_delay = serial_req.hub6 = serial_req.closing_wait = 0; - serial_req.iomem_reg_shift = 0; - if (early_serial_setup(&serial_req) < 0) { - printk("early_serial_setup() for ACPI serial console port failed\n"); - return; - } - -#ifdef SERIAL_DEBUG_ACPI - printk("Leaving setup_serial_acpi()\n"); -#endif -} diff -Nru a/drivers/char/agp/agp.c b/drivers/char/agp/agp.c --- a/drivers/char/agp/agp.c Wed Jul 24 14:03:36 2002 +++ b/drivers/char/agp/agp.c Wed Jul 24 14:03:36 2002 @@ -751,396 +751,396 @@ #ifdef CONFIG_AGP_ALI { - device_id: PCI_DEVICE_ID_AL_M1541_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1541, - vendor_name: "Ali", - chipset_name: "M1541", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1621_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1621, - vendor_name: "Ali", - chipset_name: "M1621", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1631_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1631, - vendor_name: "Ali", - chipset_name: "M1631", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1632_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1632, - vendor_name: "Ali", - chipset_name: "M1632", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1641_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1641, - vendor_name: "Ali", - chipset_name: "M1641", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1644_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1644, - vendor_name: "Ali", - chipset_name: "M1644", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1647_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1647, - vendor_name: "Ali", - chipset_name: "M1647", - chipset_setup: ali_generic_setup, - }, - { - device_id: PCI_DEVICE_ID_AL_M1651_0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_M1651, - vendor_name: "Ali", - chipset_name: "M1651", - chipset_setup: ali_generic_setup, - }, - { - device_id: 0, - vendor_id: PCI_VENDOR_ID_AL, - chipset: ALI_GENERIC, - vendor_name: "Ali", - chipset_name: "Generic", - chipset_setup: ali_generic_setup, + .device_id = PCI_DEVICE_ID_AL_M1541_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1541, + .vendor_name = "Ali", + .chipset_name = "M1541", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1621_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1621, + .vendor_name = "Ali", + .chipset_name = "M1621", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1631_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1631, + .vendor_name = "Ali", + .chipset_name = "M1631", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1632_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1632, + .vendor_name = "Ali", + .chipset_name = "M1632", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1641_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1641, + .vendor_name = "Ali", + .chipset_name = "M1641", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1644_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1644, + .vendor_name = "Ali", + .chipset_name = "M1644", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1647_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1647, + .vendor_name = "Ali", + .chipset_name = "M1647", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = PCI_DEVICE_ID_AL_M1651_0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_M1651, + .vendor_name = "Ali", + .chipset_name = "M1651", + .chipset_setup = ali_generic_setup, + }, + { + .device_id = 0, + .vendor_id = PCI_VENDOR_ID_AL, + .chipset = ALI_GENERIC, + .vendor_name = "Ali", + .chipset_name = "Generic", + .chipset_setup = ali_generic_setup, }, #endif /* CONFIG_AGP_ALI */ #ifdef CONFIG_AGP_AMD { - device_id: PCI_DEVICE_ID_AMD_IRONGATE_0, - vendor_id: PCI_VENDOR_ID_AMD, - chipset: AMD_IRONGATE, - vendor_name: "AMD", - chipset_name: "Irongate", - chipset_setup: amd_irongate_setup, - }, - { - device_id: PCI_DEVICE_ID_AMD_761_0, - vendor_id: PCI_VENDOR_ID_AMD, - chipset: AMD_761, - vendor_name: "AMD", - chipset_name: "761", - chipset_setup: amd_irongate_setup, - }, - { - device_id: PCI_DEVICE_ID_AMD_762_0, - vendor_id: PCI_VENDOR_ID_AMD, - chipset: AMD_762, - vendor_name: "AMD", - chipset_name: "760MP", - chipset_setup: amd_irongate_setup, - }, - { - device_id: 0, - vendor_id: PCI_VENDOR_ID_AMD, - chipset: AMD_GENERIC, - vendor_name: "AMD", - chipset_name: "Generic", - chipset_setup: amd_irongate_setup, + .device_id = PCI_DEVICE_ID_AMD_IRONGATE_0, + .vendor_id = PCI_VENDOR_ID_AMD, + .chipset = AMD_IRONGATE, + .vendor_name = "AMD", + .chipset_name = "Irongate", + .chipset_setup = amd_irongate_setup, + }, + { + .device_id = PCI_DEVICE_ID_AMD_761_0, + .vendor_id = PCI_VENDOR_ID_AMD, + .chipset = AMD_761, + .vendor_name = "AMD", + .chipset_name = "761", + .chipset_setup = amd_irongate_setup, + }, + { + .device_id = PCI_DEVICE_ID_AMD_762_0, + .vendor_id = PCI_VENDOR_ID_AMD, + .chipset = AMD_762, + .vendor_name = "AMD", + .chipset_name = "760MP", + .chipset_setup = amd_irongate_setup, + }, + { + .device_id = 0, + .vendor_id = PCI_VENDOR_ID_AMD, + .chipset = AMD_GENERIC, + .vendor_name = "AMD", + .chipset_name = "Generic", + .chipset_setup = amd_irongate_setup, }, #endif /* CONFIG_AGP_AMD */ #ifdef CONFIG_AGP_INTEL { - device_id: PCI_DEVICE_ID_INTEL_82443LX_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_LX, - vendor_name: "Intel", - chipset_name: "440LX", - chipset_setup: intel_generic_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_82443BX_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_BX, - vendor_name: "Intel", - chipset_name: "440BX", - chipset_setup: intel_generic_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_82443GX_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_GX, - vendor_name: "Intel", - chipset_name: "440GX", - chipset_setup: intel_generic_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_815_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I815, - vendor_name: "Intel", - chipset_name: "i815", - chipset_setup: intel_815_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_820_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I820, - vendor_name: "Intel", - chipset_name: "i820", - chipset_setup: intel_820_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_820_UP_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I820, - vendor_name: "Intel", - chipset_name: "i820", - chipset_setup: intel_820_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_830_M_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I830_M, - vendor_name: "Intel", - chipset_name: "i830M", - chipset_setup: intel_830mp_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_845_G_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I845_G, - vendor_name: "Intel", - chipset_name: "i845G", - chipset_setup: intel_830mp_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_840_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I840, - vendor_name: "Intel", - chipset_name: "i840", - chipset_setup: intel_840_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_845_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I845, - vendor_name: "Intel", - chipset_name: "i845", - chipset_setup: intel_845_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_850_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I850, - vendor_name: "Intel", - chipset_name: "i850", - chipset_setup: intel_850_setup - }, - { - device_id: PCI_DEVICE_ID_INTEL_860_0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_I860, - vendor_name: "Intel", - chipset_name: "i860", - chipset_setup: intel_860_setup - }, - { - device_id: 0, - vendor_id: PCI_VENDOR_ID_INTEL, - chipset: INTEL_GENERIC, - vendor_name: "Intel", - chipset_name: "Generic", - chipset_setup: intel_generic_setup + .device_id = PCI_DEVICE_ID_INTEL_82443LX_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_LX, + .vendor_name = "Intel", + .chipset_name = "440LX", + .chipset_setup = intel_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_82443BX_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_BX, + .vendor_name = "Intel", + .chipset_name = "440BX", + .chipset_setup = intel_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_82443GX_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_GX, + .vendor_name = "Intel", + .chipset_name = "440GX", + .chipset_setup = intel_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_815_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I815, + .vendor_name = "Intel", + .chipset_name = "i815", + .chipset_setup = intel_815_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_820_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I820, + .vendor_name = "Intel", + .chipset_name = "i820", + .chipset_setup = intel_820_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_820_UP_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I820, + .vendor_name = "Intel", + .chipset_name = "i820", + .chipset_setup = intel_820_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_830_M_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I830_M, + .vendor_name = "Intel", + .chipset_name = "i830M", + .chipset_setup = intel_830mp_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_845_G_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I845_G, + .vendor_name = "Intel", + .chipset_name = "i845G", + .chipset_setup = intel_830mp_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_840_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I840, + .vendor_name = "Intel", + .chipset_name = "i840", + .chipset_setup = intel_840_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_845_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I845, + .vendor_name = "Intel", + .chipset_name = "i845", + .chipset_setup = intel_845_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_850_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I850, + .vendor_name = "Intel", + .chipset_name = "i850", + .chipset_setup = intel_850_setup + }, + { + .device_id = PCI_DEVICE_ID_INTEL_860_0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_I860, + .vendor_name = "Intel", + .chipset_name = "i860", + .chipset_setup = intel_860_setup + }, + { + .device_id = 0, + .vendor_id = PCI_VENDOR_ID_INTEL, + .chipset = INTEL_GENERIC, + .vendor_name = "Intel", + .chipset_name = "Generic", + .chipset_setup = intel_generic_setup }, #endif /* CONFIG_AGP_INTEL */ #ifdef CONFIG_AGP_SIS { - device_id: PCI_DEVICE_ID_SI_740, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "740", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_650, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "650", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_645, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "645", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_735, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "735", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_745, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "745", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_730, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "730", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_630, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "630", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_540, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "540", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_620, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "620", - chipset_setup: sis_generic_setup - }, - { - device_id: PCI_DEVICE_ID_SI_530, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "530", - chipset_setup: sis_generic_setup + .device_id = PCI_DEVICE_ID_SI_740, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "740", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_650, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "650", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_645, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "645", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_735, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "735", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_745, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "745", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_730, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "730", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_630, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "630", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_540, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "540", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_620, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "620", + .chipset_setup = sis_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_SI_530, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "530", + .chipset_setup = sis_generic_setup }, { - device_id: PCI_DEVICE_ID_SI_550, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "550", - chipset_setup: sis_generic_setup + .device_id = PCI_DEVICE_ID_SI_550, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "550", + .chipset_setup = sis_generic_setup }, { - device_id: 0, - vendor_id: PCI_VENDOR_ID_SI, - chipset: SIS_GENERIC, - vendor_name: "SiS", - chipset_name: "Generic", - chipset_setup: sis_generic_setup + .device_id = 0, + .vendor_id = PCI_VENDOR_ID_SI, + .chipset = SIS_GENERIC, + .vendor_name = "SiS", + .chipset_name = "Generic", + .chipset_setup = sis_generic_setup }, #endif /* CONFIG_AGP_SIS */ #ifdef CONFIG_AGP_VIA { - device_id: PCI_DEVICE_ID_VIA_8501_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_MVP4, - vendor_name: "Via", - chipset_name: "MVP4", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_82C597_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_VP3, - vendor_name: "Via", - chipset_name: "VP3", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_82C598_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_MVP3, - vendor_name: "Via", - chipset_name: "MVP3", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_82C691_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_APOLLO_PRO, - vendor_name: "Via", - chipset_name: "Apollo Pro", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_8371_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_APOLLO_KX133, - vendor_name: "Via", - chipset_name: "Apollo Pro KX133", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_8363_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_APOLLO_KT133, - vendor_name: "Via", - chipset_name: "Apollo Pro KT133", - chipset_setup: via_generic_setup - }, - { - device_id: PCI_DEVICE_ID_VIA_8367_0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_APOLLO_KT133, - vendor_name: "Via", - chipset_name: "Apollo Pro KT266", - chipset_setup: via_generic_setup - }, - { - device_id: 0, - vendor_id: PCI_VENDOR_ID_VIA, - chipset: VIA_GENERIC, - vendor_name: "Via", - chipset_name: "Generic", - chipset_setup: via_generic_setup + .device_id = PCI_DEVICE_ID_VIA_8501_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_MVP4, + .vendor_name = "Via", + .chipset_name = "MVP4", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_82C597_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_VP3, + .vendor_name = "Via", + .chipset_name = "VP3", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_82C598_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_MVP3, + .vendor_name = "Via", + .chipset_name = "MVP3", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_82C691_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_APOLLO_PRO, + .vendor_name = "Via", + .chipset_name = "Apollo Pro", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_8371_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_APOLLO_KX133, + .vendor_name = "Via", + .chipset_name = "Apollo Pro KX133", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_8363_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_APOLLO_KT133, + .vendor_name = "Via", + .chipset_name = "Apollo Pro KT133", + .chipset_setup = via_generic_setup + }, + { + .device_id = PCI_DEVICE_ID_VIA_8367_0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_APOLLO_KT133, + .vendor_name = "Via", + .chipset_name = "Apollo Pro KT266", + .chipset_setup = via_generic_setup + }, + { + .device_id = 0, + .vendor_id = PCI_VENDOR_ID_VIA, + .chipset = VIA_GENERIC, + .vendor_name = "Via", + .chipset_name = "Generic", + .chipset_setup = via_generic_setup }, #endif /* CONFIG_AGP_VIA */ #ifdef CONFIG_AGP_HP_ZX1 { - device_id: PCI_DEVICE_ID_HP_ZX1_LBA, - vendor_id: PCI_VENDOR_ID_HP, - chipset: HP_ZX1, - vendor_name: "HP", - chipset_name: "ZX1", - chipset_setup: hp_zx1_setup + .device_id = PCI_DEVICE_ID_HP_ZX1_LBA, + .vendor_id = PCI_VENDOR_ID_HP, + .chipset = HP_ZX1, + .vendor_name = "HP", + .chipset_name = "ZX1", + .chipset_setup = hp_zx1_setup }, #endif @@ -1461,8 +1461,8 @@ static struct agp_version agp_current_version = { - major: AGPGART_VERSION_MAJOR, - minor: AGPGART_VERSION_MINOR, + .major = AGPGART_VERSION_MAJOR, + .minor = AGPGART_VERSION_MINOR, }; static int __init agp_backend_initialize(struct pci_dev *dev) @@ -1614,12 +1614,12 @@ static struct pci_device_id agp_pci_table[] __initdata = { { - class: (PCI_CLASS_BRIDGE_HOST << 8), - class_mask: ~0, - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { } }; @@ -1627,9 +1627,9 @@ MODULE_DEVICE_TABLE(pci, agp_pci_table); static struct pci_driver agp_pci_driver = { - name: "agpgart", - id_table: agp_pci_table, - probe: agp_probe, + .name = "agpgart", + .id_table = agp_pci_table, + .probe = agp_probe, }; static int __init agp_init(void) diff -Nru a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c --- a/drivers/char/agp/frontend.c Wed Jul 24 14:03:36 2002 +++ b/drivers/char/agp/frontend.c Wed Jul 24 14:03:36 2002 @@ -1050,14 +1050,14 @@ static struct file_operations agp_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - read: agp_read, - write: agp_write, - ioctl: agp_ioctl, - mmap: agp_mmap, - open: agp_open, - release: agp_release, + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = agp_read, + .write = agp_write, + .ioctl = agp_ioctl, + .mmap = agp_mmap, + .open = agp_open, + .release = agp_release, }; static struct miscdevice agp_miscdev = diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c --- a/drivers/char/agp/i460-agp.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/agp/i460-agp.c Wed Jul 24 14:03:38 2002 @@ -533,8 +533,8 @@ static struct gatt_mask intel_i460_masks[] = { { - mask: INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, - type: 0 + .mask = INTEL_I460_GATT_VALID | INTEL_I460_GATT_COHERENT, + .type = 0 } }; diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Wed Jul 24 14:03:39 2002 +++ b/drivers/char/amiserial.c Wed Jul 24 14:03:39 2002 @@ -2306,43 +2306,17 @@ custom.intena = IF_SETCLR | (intena & IF_TBE); } -/* - * Receive character from the serial port - */ -static int serial_console_wait_key(struct console *co) -{ - unsigned short intena = custom.intenar; - int ch; - - custom.intena = IF_RBF; - - while (!(custom.intreqr & IF_RBF)) - barrier(); - ch = custom.serdatr & 0xff; - custom.intreq = IF_RBF; - - custom.intena = IF_SETCLR | (intena & IF_RBF); - - return ch; -} - static kdev_t serial_console_device(struct console *c) { return mk_kdev(TTY_MAJOR, 64); } static struct console sercons = { - "ttyS", - serial_console_write, - NULL, - serial_console_device, - serial_console_wait_key, - NULL, - NULL, - CON_PRINTBUFFER, - -1, - 0, - NULL + .name = "ttyS", + .write = serial_console_write, + .device = serial_console_device, + .flags = CON_PRINTBUFFER, + .index = -1, }; /* diff -Nru a/drivers/char/dn_keyb.c b/drivers/char/dn_keyb.c --- a/drivers/char/dn_keyb.c Wed Jul 24 14:03:37 2002 +++ b/drivers/char/dn_keyb.c Wed Jul 24 14:03:37 2002 @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -19,8 +20,6 @@ #include "busmouse.h" -/* extern void handle_scancode(unsigned char,int ); */ - #define DNKEY_CAPS 0x7e #define BREAK_FLAG 0x80 #define DNKEY_REPEAT_DELAY 50 @@ -336,7 +335,8 @@ static short mouse_byte_count=0; static u_char mouse_packet[3]; - short mouse_buttons; + short buttons; + int dx, dy; mouse_packet[mouse_byte_count++]=mouse_data; @@ -347,24 +347,12 @@ /* printk("modechange: %d\n",mouse_packet[1]); */ if(kbd_mode==APOLLO_KBD_MODE_KEYB) dn_keyb_process_key_event(mouse_packet[2]); - } + } if((mouse_packet[0] & 0x8f) == 0x80) { - if(mouse_update_allowed) { - mouse_ready=1; - mouse_buttons=(mouse_packet[0] >> 4) & 0x7; - mouse_dx+=mouse_packet[1] == 0xff ? 0 : (signed char)mouse_packet[1]; - mouse_dy+=mouse_packet[2] == 0xff ? 0 : (signed char)mouse_packet[2]; - wake_up_interruptible(&mouse_wait); - if (mouse_dx < -2048) - mouse_dx = -2048; - else if (mouse_dx > 2048) - mouse_dx = 2048; - if (mouse_dy < -2048) - mouse_dy = -2048; - else if (mouse_dy > 2048) - mouse_dy = 2048; - kill_fasync(&mouse_fasyncptr, SIGIO, POLL_IN); - } + buttons = (mouse_packet[0] >> 4) & 0x7; + dx = mouse_packet[1] == 0xff ? 0 : (signed char)mouse_packet[1]; + dy = mouse_packet[2] == 0xff ? 0 : (signed char)mouse_packet[2]; + busmouse_add_movementbuttons(msedev, dx, dy, buttons); mouse_byte_count=0; /* printk("mouse: %d, %d, %x\n",mouse_x,mouse_y,buttons); */ } diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Wed Jul 24 14:03:39 2002 +++ b/drivers/char/hvc_console.c Wed Jul 24 14:03:39 2002 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,9 @@ static struct termios *hvc_termios[MAX_NR_HVC_CONSOLES]; static struct termios *hvc_termios_locked[MAX_NR_HVC_CONSOLES]; static int hvc_offset; +#ifdef CONFIG_MAGIC_SYSRQ +static int sysrq_pressed; +#endif #define N_OUTBUF 16 @@ -98,6 +102,14 @@ spin_unlock_irqrestore(&hp->lock, flags); } +static void hvc_hangup(struct tty_struct *tty) +{ + struct hvc_struct *hp = tty->driver_data; + + hp->count = 0; + hp->tty = NULL; +} + /* called with hp->lock held */ static void hvc_push(struct hvc_struct *hp) { @@ -186,8 +198,19 @@ n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf)); if (n <= 0) break; - for (i = 0; i < n; ++i) + for (i = 0; i < n; ++i) { +#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ + if (buf[i] == '\x0f') { /* ^O -- should support a sequence */ + sysrq_pressed = 1; + continue; + } else if (sysrq_pressed) { + handle_sysrq(buf[i], NULL, NULL, tty); + sysrq_pressed = 0; + continue; + } +#endif tty_insert_flip_char(tty, buf[i], 0); + } } if (tty->flip.count) tty_schedule_flip(tty); @@ -246,6 +269,7 @@ hvc_driver.open = hvc_open; hvc_driver.close = hvc_close; hvc_driver.write = hvc_write; + hvc_driver.hangup = hvc_hangup; hvc_driver.write_room = hvc_write_room; hvc_driver.chars_in_buffer = hvc_chars_in_buffer; diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/mem.c Wed Jul 24 14:03:38 2002 @@ -324,7 +324,7 @@ return virtr + wrote; } -#if !defined(__mc68000__) +#if defined(CONFIG_ISA) || !defined(__mc68000__) static ssize_t read_port(struct file * file, char * buf, size_t count, loff_t *ppos) { @@ -557,7 +557,7 @@ write: write_null, }; -#if !defined(__mc68000__) +#if defined(CONFIG_ISA) || !defined(__mc68000__) static struct file_operations port_fops = { llseek: memory_lseek, read: read_port, @@ -591,7 +591,7 @@ case 3: filp->f_op = &null_fops; break; -#if !defined(__mc68000__) +#if defined(CONFIG_ISA) || !defined(__mc68000__) case 4: filp->f_op = &port_fops; break; @@ -628,7 +628,9 @@ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, +#if defined(CONFIG_ISA) || !defined(__mc68000__) {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, +#endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, {7, "full", S_IRUGO | S_IWUGO, &full_fops}, {8, "random", S_IRUGO | S_IWUSR, &random_fops}, diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c --- a/drivers/char/n_tty.c Wed Jul 24 14:03:35 2002 +++ b/drivers/char/n_tty.c Wed Jul 24 14:03:35 2002 @@ -807,7 +807,7 @@ I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || I_PARMRK(tty)) { - cli(); + local_irq_disable(); // FIXME: is this safe? memset(tty->process_char_map, 0, 256/8); if (I_IGNCR(tty) || I_ICRNL(tty)) @@ -843,7 +843,7 @@ set_bit(SUSP_CHAR(tty), tty->process_char_map); } clear_bit(__DISABLED_CHAR, tty->process_char_map); - sti(); + local_irq_enable(); // FIXME: is this safe? tty->raw = 0; tty->real_raw = 0; } else { diff -Nru a/drivers/char/pcmcia/Config.in b/drivers/char/pcmcia/Config.in --- a/drivers/char/pcmcia/Config.in Wed Jul 24 14:03:35 2002 +++ b/drivers/char/pcmcia/Config.in Wed Jul 24 14:03:35 2002 @@ -5,7 +5,6 @@ mainmenu_option next_comment comment 'PCMCIA character devices' -dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA $CONFIG_SERIAL dep_tristate 'SyncLink PC Card support' CONFIG_SYNCLINK_CS $CONFIG_PCMCIA endmenu diff -Nru a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile --- a/drivers/char/pcmcia/Makefile Wed Jul 24 14:03:36 2002 +++ b/drivers/char/pcmcia/Makefile Wed Jul 24 14:03:36 2002 @@ -4,7 +4,6 @@ # Makefile for the Linux PCMCIA char device drivers. # -obj-$(CONFIG_PCMCIA_SERIAL_CS) += serial_cs.o obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o include $(TOPDIR)/Rules.make diff -Nru a/drivers/char/pcmcia/serial_cs.c b/drivers/char/pcmcia/serial_cs.c --- a/drivers/char/pcmcia/serial_cs.c Wed Jul 24 14:03:38 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,667 +0,0 @@ -/*====================================================================== - - A driver for PCMCIA serial devices - - serial_cs.c 1.123 2000/08/24 18:46:38 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#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 = -"serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; -static int irq_list[4] = { -1 }; - -/* Enable the speaker? */ -static int do_sound = 1; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); -MODULE_PARM(do_sound, "i"); - -/*====================================================================*/ - -/* Table of multi-port card ID's */ - -typedef struct { - u_short manfid; - u_short prodid; - int multi; /* 1 = multifunction, > 1 = # ports */ -} multi_id_t; - -static multi_id_t multi_id[] = { - { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, - { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, - { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, - { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } -}; -#define MULTI_COUNT (sizeof(multi_id)/sizeof(multi_id_t)) - -typedef struct serial_info_t { - dev_link_t link; - int ndev; - int multi; - int slave; - int manfid; - dev_node_t node[4]; - int line[4]; -} serial_info_t; - -static void serial_config(dev_link_t *link); -static void serial_release(u_long arg); -static int serial_event(event_t event, int priority, - event_callback_args_t *args); - -static dev_info_t dev_info = "serial_cs"; - -static dev_link_t *serial_attach(void); -static void serial_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; - -/*====================================================================*/ - -static void cs_error(client_handle_t handle, int func, int ret) -{ - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); -} - -/*====================================================================== - - serial_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static dev_link_t *serial_attach(void) -{ - serial_info_t *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; - - DEBUG(0, "serial_attach()\n"); - - /* Create new serial device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) return NULL; - memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; - - link->release.function = &serial_release; - link->release.data = (u_long)link; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_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->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - if (do_sound) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - 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 = &serial_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - serial_detach(link); - return NULL; - } - - return link; -} /* serial_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 serial_detach(dev_link_t *link) -{ - serial_info_t *info = link->priv; - dev_link_t **linkp; - int ret; - - DEBUG(0, "serial_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - - del_timer(&link->release); - if (link->state & DEV_CONFIG) - serial_release((u_long)link); - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink device structure, free bits */ - *linkp = link->next; - kfree(info); - -} /* serial_detach */ - -/*====================================================================*/ - -static int setup_serial(serial_info_t *info, ioaddr_t port, int irq) -{ - struct serial_struct serial; - int line; - - memset(&serial, 0, sizeof(serial)); - serial.port = port; - serial.irq = irq; - serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; - line = register_serial(&serial); - if (line < 0) { - printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," - " irq %d failed\n", (u_long)serial.port, serial.irq); - return -1; - } - - info->line[info->ndev] = line; - sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); - info->node[info->ndev].major = TTY_MAJOR; - info->node[info->ndev].minor = 0x40+line; - if (info->ndev > 0) - info->node[info->ndev-1].next = &info->node[info->ndev]; - info->ndev++; - - return 0; -} - -/*====================================================================*/ - -static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, - cisparse_t *parse) -{ - int i; - i = CardServices(fn, handle, tuple); - if (i != CS_SUCCESS) return CS_NO_MORE_ITEMS; - i = CardServices(GetTupleData, handle, tuple); - if (i != CS_SUCCESS) return i; - return CardServices(ParseTuple, handle, tuple, parse); -} - -#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) -#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) - -/*====================================================================*/ - -static int simple_config(dev_link_t *link) -{ - static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - client_handle_t handle = link->handle; - serial_info_t *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; - int i, j, try; - - /* If the card is already configured, look up the port and irq */ - i = CardServices(GetConfigurationInfo, handle, &config); - if ((i == CS_SUCCESS) && - (config.Attributes & CONF_VALID_CLIENT)) { - ioaddr_t port = 0; - if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { - port = config.BasePort2; - info->slave = 1; - } else if ((info->manfid == MANFID_OSITECH) && - (config.NumPorts1 == 0x40)) { - port = config.BasePort1 + 0x28; - info->slave = 1; - } - if (info->slave) - return setup_serial(info, port, config.AssignedIRQ); - } - link->conf.Vcc = config.Vcc; - - /* First pass: look for a config entry that looks normal. */ - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - /* Two tries: without IO aliases, then with aliases */ - for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if (i != CS_SUCCESS) goto next_entry; - if (cf->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = - cf->vpp1.param[CISTPL_POWER_VNOM]/10000; - if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && - (cf->io.win[0].base != 0)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = (try == 0) ? - 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - if (i == CS_SUCCESS) goto found_port; - } - next_entry: - i = next_tuple(handle, &tuple, &parse); - } - } - - /* Second pass: try to find an entry that isn't picky about - its base address, then try to grab any standard serial port - address, and finally try to get any free port. */ - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && - ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { - link->conf.ConfigIndex = cf->index; - for (j = 0; j < 5; j++) { - link->io.BasePort1 = base[j]; - link->io.IOAddrLines = base[j] ? 16 : 3; - i = CardServices(RequestIO, link->handle, - &link->io); - if (i == CS_SUCCESS) goto found_port; - } - } - i = next_tuple(handle, &tuple, &parse); - } - -found_port: - if (i != CS_SUCCESS) { - printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIO, i); - return -1; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - if (info->multi && (info->manfid == MANFID_3COM)) - link->conf.ConfigIndex &= ~(0x08); - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - return -1; - } - - return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); -} - -static int multi_config(dev_link_t *link) -{ - client_handle_t handle = link->handle; - serial_info_t *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, base2 = 0; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - - /* First, look for a generic full-sized window */ - link->io.NumPorts1 = info->multi * 8; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - /* The quad port cards have bad CIS's, so just look for a - window larger than 8 ports and assume it will be right */ - if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && - (cf->io.win[0].len > 8)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - base2 = link->io.BasePort1 + 8; - if (i == CS_SUCCESS) break; - } - i = next_tuple(handle, &tuple, &parse); - } - - /* If that didn't work, look for two windows */ - if (i != CS_SUCCESS) { - link->io.NumPorts1 = link->io.NumPorts2 = 8; - info->multi = 2; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.BasePort2 = cf->io.win[1].base; - link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - base2 = link->io.BasePort2; - if (i == CS_SUCCESS) break; - } - i = next_tuple(handle, &tuple, &parse); - } - } - - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); - return -1; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - /* Socket Dual IO: this enables irq's for second port */ - if (info->multi && (info->manfid == MANFID_SOCKET)) { - link->conf.Present |= PRESENT_EXT_STATUS; - link->conf.ExtStatus = ESR_REQ_ATTN_ENA; - } - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - return -1; - } - - setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); - /* The Nokia cards are not really multiport cards */ - if (info->manfid == MANFID_NOKIA) - return 0; - for (i = 0; i < info->multi-1; i++) - setup_serial(info, base2+(8*i), link->irq.AssignedIRQ); - - return 0; -} - -/*====================================================================== - - serial_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - serial device available to the system. - -======================================================================*/ - -#define CS_CHECK(fn, args...) \ -while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed - -void serial_config(dev_link_t *link) -{ - client_handle_t handle = link->handle; - serial_info_t *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, last_ret, last_fn; - - DEBUG(0, "serial_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); - if (last_ret != 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; - - /* Is this a compliant multifunction card? */ - tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; - info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); - - /* Is this a multiport card? */ - tuple.DesiredTuple = CISTPL_MANFID; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - info->manfid = le16_to_cpu(buf[0]); - for (i = 0; i < MULTI_COUNT; i++) - if ((info->manfid == multi_id[i].manfid) && - (le16_to_cpu(buf[1]) == multi_id[i].prodid)) - break; - if (i < MULTI_COUNT) - info->multi = multi_id[i].multi; - } - - /* Another check for dual-serial cards: look for either serial or - multifunction cards that ask for appropriate IO port ranges */ - tuple.DesiredTuple = CISTPL_FUNCID; - if ((info->multi == 0) && - ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || - (parse.funcid.func == CISTPL_FUNCID_MULTI) || - (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) - info->multi = cf->io.win[0].len >> 3; - if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && - (cf->io.win[1].len == 8)) - info->multi = 2; - } - } - - if (info->multi > 1) - multi_config(link); - else - simple_config(link); - - if (info->ndev == 0) - goto failed; - - if (info->manfid == MANFID_IBM) { - conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; - CS_CHECK(AccessConfigurationRegister, link->handle, ®); - reg.Action = CS_WRITE; - reg.Value = reg.Value | 1; - CS_CHECK(AccessConfigurationRegister, link->handle, ®); - } - - link->dev = &info->node[0]; - link->state &= ~DEV_CONFIG_PENDING; - return; - -cs_failed: - cs_error(link->handle, last_fn, last_ret); -failed: - serial_release((u_long)link); - -} /* serial_config */ - -/*====================================================================== - - After a card is removed, serial_release() will unregister the net - device, and release the PCMCIA configuration. - -======================================================================*/ - -void serial_release(u_long arg) -{ - dev_link_t *link = (dev_link_t *)arg; - serial_info_t *info = link->priv; - int i; - - DEBUG(0, "serial_release(0x%p)\n", link); - - for (i = 0; i < info->ndev; i++) { - unregister_serial(info->line[i]); - } - link->dev = NULL; - - if (!info->slave) { - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - } - - link->state &= ~DEV_CONFIG; - -} /* serial_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 serial drivers from - talking to the ports. - -======================================================================*/ - -static int serial_event(event_t event, int priority, - event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - serial_info_t *info = link->priv; - - DEBUG(1, "serial_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ/20); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - serial_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if ((link->state & DEV_CONFIG) && !info->slave) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link) && !info->slave) - CardServices(RequestConfiguration, link->handle, &link->conf); - break; - } - return 0; -} /* serial_event */ - -/*====================================================================*/ - -static int __init init_serial_cs(void) -{ - servinfo_t serv; - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "serial_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &serial_attach, &serial_detach); - return 0; -} - -static void __exit exit_serial_cs(void) -{ - DEBUG(0, "serial_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - serial_detach(dev_list); -} - -module_init(init_serial_cs); -module_exit(exit_serial_cs); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/q40_keyb.c b/drivers/char/q40_keyb.c --- a/drivers/char/q40_keyb.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/q40_keyb.c Wed Jul 24 14:03:38 2002 @@ -31,9 +31,6 @@ #include #include -/* Some configuration switches are present in the include file... */ - -#define KBD_REPORT_ERR /* Simple translation table for the SysRq keys */ @@ -215,7 +212,6 @@ 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */ }; -static unsigned int prev_scancode = 0; /* remember E0, E1 */ int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode) { @@ -246,10 +242,21 @@ int q40kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) { - if (scancode == 0xe0 || scancode == 0xe1) { + static int prev_scancode; + + /* special prefix scancodes.. */ + if (scancode == 0xe0 || scancode == 0xe1) { prev_scancode = scancode; return 0; - } + } + + /* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */ + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; + return 0; + } + + scancode &= 0x7f; if (prev_scancode) { /* @@ -408,8 +415,6 @@ return retval; } -extern void q40kbd_leds(unsigned char leds) -{ /* nothing can be done */ } static void __init kbd_clear_input(void) { @@ -422,12 +427,9 @@ } -void __init q40kbd_init_hw(void) +int __init q40kbd_init_hw(void) { -#if 0 - /* Get the keyboard controller registers (incomplete decode) */ - request_region(0x60, 16, "keyboard"); -#endif + /* Flush any pending input. */ kbd_clear_input(); @@ -436,5 +438,6 @@ master_outb(-1,KEYBOARD_UNLOCK_REG); master_outb(1,KEY_IRQ_ENABLE_REG); + return 0; } diff -Nru a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c --- a/drivers/char/ser_a2232.c Wed Jul 24 14:03:37 2002 +++ b/drivers/char/ser_a2232.c Wed Jul 24 14:03:37 2002 @@ -90,6 +90,7 @@ #include #include #include +#include #include #include diff -Nru a/drivers/char/serial.c b/drivers/char/serial.c --- a/drivers/char/serial.c Wed Jul 24 14:03:37 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,6003 +0,0 @@ -/* - * linux/drivers/char/serial.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, - * 1998, 1999 Theodore Ts'o - * - * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now - * much more extensible to support other serial cards based on the - * 16450/16550A UART's. Added support for the AST FourPort and the - * Accent Async board. - * - * set_serial_info fixed to set the flags, custom divisor, and uart - * type fields. Fix suggested by Michael K. Johnson 12/12/92. - * - * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis - * - * 03/96: Modularised by Angelo Haritsis - * - * rs_set_termios fixed to look also for changes of the input - * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. - * Bernd Anhäupl 05/17/96. - * - * 1/97: Extended dumb serial ports are a config option now. - * Saves 4k. Michael A. Griffith - * - * 8/97: Fix bug in rs_set_termios with RTS - * Stanislav V. Voronyi - * - * 3/98: Change the IRQ detection, use of probe_irq_o*(), - * suppress TIOCSERGWILD and TIOCSERSWILD - * Etienne Lorrain - * - * 4/98: Added changes to support the ARM architecture proposed by - * Russell King - * - * 5/99: Updated to include support for the XR16C850 and ST16C654 - * uarts. Stuart MacDonald - * - * 8/99: Generalized PCI support added. Theodore Ts'o - * - * 3/00: Rid circular buffer of redundant xmit_cnt. Fix a - * few races on freeing buffers too. - * Alan Modra - * - * 5/00: Support for the RSA-DV II/S card added. - * Kiyokazu SUTO - * - * 6/00: Remove old-style timer, use timer_list - * Andrew Morton - * - * 7/00: Support Timedia/Sunix/Exsys PCI cards - * - * 7/00: fix some returns on failure not using MOD_DEC_USE_COUNT. - * Arnaldo Carvalho de Melo - * - * 10/00: add in optional software flow control for serial console. - * Kanoj Sarcar (Modified by Theodore Ts'o) - * - */ - -static char *serial_version = "5.05c"; -static char *serial_revdate = "2001-07-08"; - -/* - * Serial driver configuration section. Here are the various options: - * - * CONFIG_HUB6 - * Enables support for the venerable Bell Technologies - * HUB6 card. - * - * CONFIG_SERIAL_MANY_PORTS - * Enables support for ports beyond the standard, stupid - * COM 1/2/3/4. - * - * CONFIG_SERIAL_MULTIPORT - * Enables support for special multiport board support. - * - * CONFIG_SERIAL_SHARE_IRQ - * Enables support for multiple serial ports on one IRQ - * - * CONFIG_SERIAL_DETECT_IRQ - * Enable the autodetection of IRQ on standart ports - * - * SERIAL_PARANOIA_CHECK - * Check the magic number for the async_structure where - * ever possible. - * - * CONFIG_SERIAL_ACPI - * Enable support for serial console port and serial - * debug port as defined by the SPCR and DBGP tables in - * ACPI 2.0. - */ - -#include -#include - -#undef SERIAL_PARANOIA_CHECK -#define CONFIG_SERIAL_NOPAUSE_IO -#define SERIAL_DO_RESTART - -#if 0 -/* These defines are normally controlled by the autoconf.h */ -#define CONFIG_SERIAL_MANY_PORTS -#define CONFIG_SERIAL_SHARE_IRQ -#define CONFIG_SERIAL_DETECT_IRQ -#define CONFIG_SERIAL_MULTIPORT -#define CONFIG_HUB6 -#endif - -#ifdef CONFIG_PCI -#define ENABLE_SERIAL_PCI -#ifndef CONFIG_SERIAL_SHARE_IRQ -#define CONFIG_SERIAL_SHARE_IRQ -#endif -#ifndef CONFIG_SERIAL_MANY_PORTS -#define CONFIG_SERIAL_MANY_PORTS -#endif -#endif - -#ifdef CONFIG_SERIAL_ACPI -#define ENABLE_SERIAL_ACPI -#endif - - -/* Set of debugging defines */ - -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW -#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT -#undef SERIAL_DEBUG_PCI -#undef SERIAL_DEBUG_AUTOCONF - -/* Sanity checks */ - -#ifdef CONFIG_SERIAL_MULTIPORT -#ifndef CONFIG_SERIAL_SHARE_IRQ -#define CONFIG_SERIAL_SHARE_IRQ -#endif -#endif - -#ifdef CONFIG_HUB6 -#ifndef CONFIG_SERIAL_MANY_PORTS -#define CONFIG_SERIAL_MANY_PORTS -#endif -#ifndef CONFIG_SERIAL_SHARE_IRQ -#define CONFIG_SERIAL_SHARE_IRQ -#endif -#endif - -#ifdef MODULE -#undef CONFIG_SERIAL_CONSOLE -#endif - -#define CONFIG_SERIAL_RSA - -#define RS_STROBE_TIME (10*HZ) -#define RS_ISR_PASS_LIMIT 256 - -#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) -#define SERIAL_INLINE -#endif - -/* - * End of serial driver configuration section. - */ - -#include - -#include -#ifdef LOCAL_HEADERS -#include "serial_local.h" -#else -#include -#include -#include -#include -#define LOCAL_VERSTRING "" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE >= 131343) -#include -#endif -#if (LINUX_VERSION_CODE >= 131336) -#include -#endif -#include -#ifdef CONFIG_SERIAL_CONSOLE -#include -#endif -#ifdef ENABLE_SERIAL_PCI -#include -#endif - -#include -#ifdef __ISAPNP__ -#ifndef ENABLE_SERIAL_PNP -#define ENABLE_SERIAL_PNP -#endif -#endif - -#ifdef CONFIG_MAGIC_SYSRQ -#include -#endif - -/* - * All of the compatibilty code so we can compile serial.c against - * older kernels is hidden in serial_compat.h - */ -#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */ -#include "serial_compat.h" -#endif - -#include -#include -#include -#include - -#ifdef CONFIG_MAC_SERIAL -#define SERIAL_DEV_OFFSET 2 -#else -#define SERIAL_DEV_OFFSET 0 -#endif - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#else -#define _INLINE_ -#endif - -static char *serial_name = "Serial driver"; - -static DECLARE_TASK_QUEUE(tq_serial); - -static struct tty_driver serial_driver, callout_driver; -static int serial_refcount; - -static struct timer_list serial_timer; - -/* serial subtype definitions */ -#ifndef SERIAL_TYPE_NORMAL -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 -#endif - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* - * IRQ_timeout - How long the timeout should be for each IRQ - * should be after the IRQ has been active. - */ - -static struct async_struct *IRQ_ports[NR_IRQS]; -#ifdef CONFIG_SERIAL_MULTIPORT -static struct rs_multiport_struct rs_multiport[NR_IRQS]; -#endif -static int IRQ_timeout[NR_IRQS]; -#ifdef CONFIG_SERIAL_CONSOLE -static struct console sercons; -static int lsr_break_flag; -#endif -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -static unsigned long break_pressed; /* break, really ... */ -#endif - -static unsigned detect_uart_irq (struct serial_state * state); -static void autoconfig(struct serial_state * state); -static void change_speed(struct async_struct *info, struct termios *old); -static void rs_wait_until_sent(struct tty_struct *tty, int timeout); - -/* - * Here we define the default xmit fifo size used for each type of - * UART - */ -static struct serial_uart_config uart_config[] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, - { "cirrus", 1, 0 }, /* usurped by cyclades.c */ - { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, - { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | - UART_STARTECH }, - { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO}, - { "Startech", 1, 0}, /* usurped by cyclades.c */ - { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO}, - { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | - UART_STARTECH }, - { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | - UART_STARTECH }, - { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO }, - { 0, 0} -}; - -#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) - -#define PORT_RSA_MAX 4 -static int probe_rsa[PORT_RSA_MAX]; -static int force_rsa[PORT_RSA_MAX]; - -MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); -MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); -MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); -MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA"); -#endif /* CONFIG_SERIAL_RSA */ - -static struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in serial.h */ -}; - -#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) - -#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)) -#define NR_PCI_BOARDS 8 - -static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS]; - -#ifndef IS_PCI_REGION_IOPORT -#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_IO) -#endif -#ifndef IS_PCI_REGION_IOMEM -#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_MEM) -#endif -#ifndef PCI_IRQ_RESOURCE -#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) -#endif -#ifndef pci_get_subvendor -#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) -#define pci_get_subdevice(dev) ((dev)->subsystem_device) -#endif -#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ - -#ifndef PREPARE_FUNC -#define PREPARE_FUNC(dev) (dev->prepare) -#define ACTIVATE_FUNC(dev) (dev->activate) -#define DEACTIVATE_FUNC(dev) (dev->deactivate) -#endif - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - -static struct tty_struct *serial_table[NR_PORTS]; -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; - - -#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) -#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ - kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s) -#else -#define DBG_CNT(s) -#endif - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -#ifdef DECLARE_MUTEX -static DECLARE_MUTEX(tmp_buf_sem); -#else -static struct semaphore tmp_buf_sem = MUTEX; -#endif - - -static inline int serial_paranoia_check(struct async_struct *info, - kdev_t device, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null async_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, kdevname(device), routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, kdevname(device), routine); - return 1; - } -#endif - return 0; -} - -static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) -{ - switch (info->io_type) { -#ifdef CONFIG_HUB6 - case SERIAL_IO_HUB6: - outb(info->hub6 - 1 + offset, info->port); - return inb(info->port+1); -#endif - case SERIAL_IO_MEM: - return readb((unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); -#ifdef CONFIG_SERIAL_GSC - case SERIAL_IO_GSC: - return gsc_readb(info->iomem_base + offset); -#endif - default: - return inb(info->port + offset); - } -} - -static _INLINE_ void serial_out(struct async_struct *info, int offset, - int value) -{ - switch (info->io_type) { -#ifdef CONFIG_HUB6 - case SERIAL_IO_HUB6: - outb(info->hub6 - 1 + offset, info->port); - outb(value, info->port+1); - break; -#endif - case SERIAL_IO_MEM: - writeb(value, (unsigned long) info->iomem_base + - (offset<iomem_reg_shift)); - break; -#ifdef CONFIG_SERIAL_GSC - case SERIAL_IO_GSC: - gsc_writeb(value, info->iomem_base + offset); - break; -#endif - default: - outb(value, info->port+offset); - } -} - -/* - * We used to support using pause I/O for certain machines. We - * haven't supported this for a while, but just in case it's badly - * needed for certain old 386 machines, I've left these #define's - * in.... - */ -#define serial_inp(info, offset) serial_in(info, offset) -#define serial_outp(info, offset, value) serial_out(info, offset, value) - - -/* - * For the 16C950 - */ -void serial_icr_write(struct async_struct *info, int offset, int value) -{ - serial_out(info, UART_SCR, offset); - serial_out(info, UART_ICR, value); -} - -unsigned int serial_icr_read(struct async_struct *info, int offset) -{ - int value; - - serial_icr_write(info, UART_ACR, info->ACR | UART_ACR_ICRRD); - serial_out(info, UART_SCR, offset); - value = serial_in(info, UART_ICR); - serial_icr_write(info, UART_ACR, info->ACR); - return value; -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_stop")) - return; - - save_flags(flags); cli(); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - if (info->state->type == PORT_16C950) { - info->ACR |= UART_ACR_TXDIS; - serial_icr_write(info, UART_ACR, info->ACR); - } - restore_flags(flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_start")) - return; - - save_flags(flags); cli(); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - if (info->state->type == PORT_16C950) { - info->ACR &= ~UART_ACR_TXDIS; - serial_icr_write(info, UART_ACR, info->ACR); - } - restore_flags(flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_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: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static _INLINE_ void rs_sched_event(struct async_struct *info, - int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - -static _INLINE_ void receive_chars(struct async_struct *info, - int *status, struct pt_regs * regs) -{ - struct tty_struct *tty = info->tty; - unsigned char ch; - struct async_icount *icount; - int max_count = 256; - - icount = &info->state->icount; - do { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty->flip.tqueue.routine((void *) tty); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set - } - ch = serial_inp(info, UART_RX); - *tty->flip.char_buf_ptr = ch; - icount->rx++; - -#ifdef SERIAL_DEBUG_INTR - printk("DR%02x:%02x...", ch, *status); -#endif - *tty->flip.flag_buf_ptr = 0; - if (*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); - 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 defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - if (info->line == sercons.index) { - if (!break_pressed) { - break_pressed = jiffies; - goto ignore_char; - } - break_pressed = 0; - } -#endif - if (info->flags & ASYNC_SAK) - do_SAK(tty); - } else if (*status & UART_LSR_PE) - icount->parity++; - else if (*status & UART_LSR_FE) - icount->frame++; - if (*status & UART_LSR_OE) - icount->overrun++; - - /* - * Mask off conditions which should be ignored. - */ - *status &= info->read_status_mask; - -#ifdef CONFIG_SERIAL_CONSOLE - if (info->line == sercons.index) { - /* Recover the break flag from console xmit */ - *status |= lsr_break_flag; - lsr_break_flag = 0; - } -#endif - if (*status & (UART_LSR_BI)) { -#ifdef SERIAL_DEBUG_INTR - printk("handling break...."); -#endif - *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 defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - if (break_pressed && info->line == sercons.index) { - if (ch != 0 && - time_before(jiffies, break_pressed + HZ*5)) { - handle_sysrq(ch, regs, NULL); - break_pressed = 0; - goto ignore_char; - } - break_pressed = 0; - } -#endif - if ((*status & info->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.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - } -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - ignore_char: -#endif - *status = serial_inp(info, UART_LSR); - } while ((*status & UART_LSR_DR) && (max_count-- > 0)); -#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */ - tty_flip_buffer_push(tty); -#else - queue_task_irq_off(&tty->flip.tqueue, &tq_timer); -#endif -} - -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) -{ - int count; - - if (info->x_char) { - serial_outp(info, UART_TX, info->x_char); - info->state->icount.tx++; - info->x_char = 0; - if (intr_done) - *intr_done = 0; - return; - } - if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - return; - } - - count = info->xmit_fifo_size; - do { - serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]); - info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); - info->state->icount.tx++; - if (info->xmit.head == info->xmit.tail) - break; - } while (--count > 0); - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - -#ifdef SERIAL_DEBUG_INTR - printk("THRE..."); -#endif - if (intr_done) - *intr_done = 0; - - if (info->xmit.head == info->xmit.tail) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } -} - -static _INLINE_ void check_modem_status(struct async_struct *info) -{ - int status; - struct async_icount *icount; - - status = serial_in(info, UART_MSR); - - if (status & UART_MSR_ANY_DELTA) { - icount = &info->state->icount; - /* update input line counters */ - if (status & UART_MSR_TERI) - icount->rng++; - if (status & UART_MSR_DDSR) - icount->dsr++; - if (status & UART_MSR_DDCD) { - icount->dcd++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - (status & UART_MSR_DCD)) - hardpps(); -#endif - } - if (status & UART_MSR_DCTS) - icount->cts++; - wake_up_interruptible(&info->delta_msr_wait); - } - - if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttys%d CD now %s...", info->line, - (status & UART_MSR_DCD) ? "on" : "off"); -#endif - if (status & UART_MSR_DCD) - wake_up_interruptible(&info->open_wait); - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_CALLOUT_NOHUP))) { -#ifdef SERIAL_DEBUG_OPEN - printk("doing serial hangup..."); -#endif - if (info->tty) - tty_hangup(info->tty); - } - } - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { - if (status & UART_MSR_CTS) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx start..."); -#endif - info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - return; - } - } else { - if (!(status & UART_MSR_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx stop..."); -#endif - info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - } - } -} - -#ifdef CONFIG_SERIAL_SHARE_IRQ -/* - * This is the serial driver's generic interrupt routine - */ -static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - int status; - struct async_struct * info; - int pass_counter = 0; - struct async_struct *end_mark = 0; -#ifdef CONFIG_SERIAL_MULTIPORT - int first_multi = 0; - struct rs_multiport_struct *multi; -#endif - -#ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt(%d)...", irq); -#endif - - info = IRQ_ports[irq]; - if (!info) - return; - -#ifdef CONFIG_SERIAL_MULTIPORT - multi = &rs_multiport[irq]; - if (multi->port_monitor) - first_multi = inb(multi->port_monitor); -#endif - - do { - if (!info->tty || - (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) { - if (!end_mark) - end_mark = info; - goto next; - } -#ifdef SERIAL_DEBUG_INTR - printk("IIR = %x...", serial_in(info, UART_IIR)); -#endif - end_mark = 0; - - info->last_active = jiffies; - - status = serial_inp(info, UART_LSR); -#ifdef SERIAL_DEBUG_INTR - printk("status = %x...", status); -#endif - if (status & UART_LSR_DR) - receive_chars(info, &status, regs); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - - next: - info = info->next_port; - if (!info) { - info = IRQ_ports[irq]; - if (pass_counter++ > RS_ISR_PASS_LIMIT) { -#if 0 - printk("rs loop break\n"); -#endif - break; /* Prevent infinite loops */ - } - continue; - } - } while (end_mark != info); -#ifdef CONFIG_SERIAL_MULTIPORT - if (multi->port_monitor) - printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", - info->state->irq, first_multi, - inb(multi->port_monitor)); -#endif -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif -} -#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ - - -/* - * This is the serial driver's interrupt routine for a single port - */ -static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) -{ - int status; - int pass_counter = 0; - struct async_struct * info; -#ifdef CONFIG_SERIAL_MULTIPORT - int first_multi = 0; - struct rs_multiport_struct *multi; -#endif - -#ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); -#endif - - info = IRQ_ports[irq]; - if (!info || !info->tty) - return; - -#ifdef CONFIG_SERIAL_MULTIPORT - multi = &rs_multiport[irq]; - if (multi->port_monitor) - first_multi = inb(multi->port_monitor); -#endif - - do { - status = serial_inp(info, UART_LSR); -#ifdef SERIAL_DEBUG_INTR - printk("status = %x...", status); -#endif - if (status & UART_LSR_DR) - receive_chars(info, &status, regs); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - if (pass_counter++ > RS_ISR_PASS_LIMIT) { -#if 0 - printk("rs_single loop break.\n"); -#endif - break; - } -#ifdef SERIAL_DEBUG_INTR - printk("IIR = %x...", serial_in(info, UART_IIR)); -#endif - } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); - info->last_active = jiffies; -#ifdef CONFIG_SERIAL_MULTIPORT - if (multi->port_monitor) - printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", - info->state->irq, first_multi, - inb(multi->port_monitor)); -#endif -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif -} - -#ifdef CONFIG_SERIAL_MULTIPORT -/* - * This is the serial driver's for multiport boards - */ -static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) -{ - int status; - struct async_struct * info; - int pass_counter = 0; - int first_multi= 0; - struct rs_multiport_struct *multi; - -#ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_multi(%d)...", irq); -#endif - - info = IRQ_ports[irq]; - if (!info) - return; - multi = &rs_multiport[irq]; - if (!multi->port1) { - /* Should never happen */ - printk("rs_interrupt_multi: NULL port1!\n"); - return; - } - if (multi->port_monitor) - first_multi = inb(multi->port_monitor); - - while (1) { - if (!info->tty || - (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) - goto next; - - info->last_active = jiffies; - - status = serial_inp(info, UART_LSR); -#ifdef SERIAL_DEBUG_INTR - printk("status = %x...", status); -#endif - if (status & UART_LSR_DR) - receive_chars(info, &status, regs); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - - next: - info = info->next_port; - if (info) - continue; - - info = IRQ_ports[irq]; - /* - * The user was a bonehead, and misconfigured their - * multiport info. Rather than lock up the kernel - * in an infinite loop, if we loop too many times, - * print a message and break out of the loop. - */ - if (pass_counter++ > RS_ISR_PASS_LIMIT) { - printk("Misconfigured multiport serial info " - "for irq %d. Breaking out irq loop\n", irq); - break; - } - if (multi->port_monitor) - printk("rs port monitor irq %d: 0x%x, 0x%x\n", - info->state->irq, first_multi, - inb(multi->port_monitor)); - if ((inb(multi->port1) & multi->mask1) != multi->match1) - continue; - if (!multi->port2) - break; - if ((inb(multi->port2) & multi->mask2) != multi->match2) - continue; - if (!multi->port3) - break; - if ((inb(multi->port3) & multi->mask3) != multi->match3) - continue; - if (!multi->port4) - break; - if ((inb(multi->port4) & multi->mask4) != multi->match4) - continue; - break; - } -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif -} -#endif - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); -} - -static void do_softint(void *private_) -{ - struct async_struct *info = (struct async_struct *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); -#ifdef SERIAL_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - } -} - -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * by the serial driver to handle ports that do not have an interrupt - * (irq=0). 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 rs_timer(unsigned long dummy) -{ - static unsigned long last_strobe; - struct async_struct *info; - unsigned int i; - unsigned long flags; - - if ((jiffies - last_strobe) >= RS_STROBE_TIME) { - for (i=0; i < NR_IRQS; i++) { - info = IRQ_ports[i]; - if (!info) - continue; - save_flags(flags); cli(); -#ifdef CONFIG_SERIAL_SHARE_IRQ - if (info->next_port) { - do { - serial_out(info, UART_IER, 0); - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - info = info->next_port; - } while (info); -#ifdef CONFIG_SERIAL_MULTIPORT - if (rs_multiport[i].port1) - rs_interrupt_multi(i, NULL, NULL); - else -#endif - rs_interrupt(i, NULL, NULL); - } else -#endif /* CONFIG_SERIAL_SHARE_IRQ */ - rs_interrupt_single(i, NULL, NULL); - restore_flags(flags); - } - } - last_strobe = jiffies; - mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); - - if (IRQ_ports[0]) { - save_flags(flags); cli(); -#ifdef CONFIG_SERIAL_SHARE_IRQ - rs_interrupt(0, NULL, NULL); -#else - rs_interrupt_single(0, NULL, NULL); -#endif - restore_flags(flags); - - mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); - } -} - -/* - * --------------------------------------------------------------- - * Low level utility subroutines for the serial driver: routines to - * figure out the appropriate timeout for an interrupt chain, routines - * to initialize and startup a serial port, and routines to shutdown a - * serial port. Useful stuff like that. - * --------------------------------------------------------------- - */ - -/* - * This routine figures out the correct timeout for a particular IRQ. - * It uses the smallest timeout of all of the serial ports in a - * particular interrupt chain. Now only used for IRQ 0.... - */ -static void figure_IRQ_timeout(int irq) -{ - struct async_struct *info; - int timeout = 60*HZ; /* 60 seconds === a long time :-) */ - - info = IRQ_ports[irq]; - if (!info) { - IRQ_timeout[irq] = 60*HZ; - return; - } - while (info) { - if (info->timeout < timeout) - timeout = info->timeout; - info = info->next_port; - } - if (!irq) - timeout = timeout / 2; - IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; -} - -#ifdef CONFIG_SERIAL_RSA -/* Attempts to turn on the RSA FIFO. Returns zero on failure */ -static int enable_rsa(struct async_struct *info) -{ - unsigned char mode; - int result; - unsigned long flags; - - save_flags(flags); cli(); - mode = serial_inp(info, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; - - if (!result) { - serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); - mode = serial_inp(info, UART_RSA_MSR); - result = mode & UART_RSA_MSR_FIFO; - } - - restore_flags(flags); - return result; -} - -/* Attempts to turn off the RSA FIFO. Returns zero on failure */ -static int disable_rsa(struct async_struct *info) -{ - unsigned char mode; - int result; - unsigned long flags; - - save_flags(flags); cli(); - mode = serial_inp(info, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - - if (!result) { - serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); - mode = serial_inp(info, UART_RSA_MSR); - result = !(mode & UART_RSA_MSR_FIFO); - } - - restore_flags(flags); - return result; -} -#endif /* CONFIG_SERIAL_RSA */ - -static int startup(struct async_struct * info) -{ - unsigned long flags; - int retval=0; - void (*handler)(int, void *, struct pt_regs *); - struct serial_state *state= info->state; - unsigned long page; -#ifdef CONFIG_SERIAL_MANY_PORTS - unsigned short ICP; -#endif - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (!CONFIGURED_SERIAL_PORT(state) || !state->type) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - free_page(page); - goto errout; - } - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - -#ifdef SERIAL_DEBUG_OPEN - printk("starting up ttys%d (irq %d)...", info->line, state->irq); -#endif - - if (uart_config[state->type].flags & UART_STARTECH) { - /* Wake up UART */ - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, UART_EFR_ECB); - /* - * Turn off LCR == 0xBF so we actually set the IER - * register on the XR16C850 - */ - serial_outp(info, UART_LCR, 0); - serial_outp(info, UART_IER, 0); - /* - * Now reset LCR so we can turn off the ECB bit - */ - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, 0); - /* - * For a XR16C850, we need to set the trigger levels - */ - if (state->type == PORT_16850) { - serial_outp(info, UART_FCTR, UART_FCTR_TRGD | - UART_FCTR_RX); - serial_outp(info, UART_TRG, UART_TRG_96); - serial_outp(info, UART_FCTR, UART_FCTR_TRGD | - UART_FCTR_TX); - serial_outp(info, UART_TRG, UART_TRG_96); - } - serial_outp(info, UART_LCR, 0); - } - - if (state->type == PORT_16750) { - /* Wake up UART */ - serial_outp(info, UART_IER, 0); - } - - if (state->type == PORT_16C950) { - /* Wake up and initialize UART */ - info->ACR = 0; - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, UART_EFR_ECB); - serial_outp(info, UART_IER, 0); - serial_outp(info, UART_LCR, 0); - serial_icr_write(info, UART_CSR, 0); /* Reset the UART */ - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, UART_EFR_ECB); - serial_outp(info, UART_LCR, 0); - } - -#ifdef CONFIG_SERIAL_RSA - /* - * If this is an RSA port, see if we can kick it up to the - * higher speed clock. - */ - if (state->type == PORT_RSA) { - if (state->baud_base != SERIAL_RSA_BAUD_BASE && - enable_rsa(info)) - state->baud_base = SERIAL_RSA_BAUD_BASE; - if (state->baud_base == SERIAL_RSA_BAUD_BASE) - serial_outp(info, UART_RSA_FRR, 0); - } -#endif - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - if (uart_config[state->type].flags & UART_CLEAR_FIFO) { - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - } - - /* - * Clear the interrupt registers. - */ - (void) serial_inp(info, UART_LSR); - (void) serial_inp(info, UART_RX); - (void) serial_inp(info, UART_IIR); - (void) serial_inp(info, 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 (!(info->flags & ASYNC_BUGGY_UART) && - (serial_inp(info, UART_LSR) == 0xff)) { - printk("ttyS%d: LSR safety check engaged!\n", state->line); - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - } else - retval = -ENODEV; - goto errout; - } - - /* - * Allocate the IRQ if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { -#ifdef CONFIG_SERIAL_SHARE_IRQ - free_irq(state->irq, &IRQ_ports[state->irq]); -#ifdef CONFIG_SERIAL_MULTIPORT - if (rs_multiport[state->irq].port1) - handler = rs_interrupt_multi; - else -#endif - handler = rs_interrupt; -#else - retval = -EBUSY; - goto errout; -#endif /* CONFIG_SERIAL_SHARE_IRQ */ - } else - handler = rs_interrupt_single; - - retval = request_irq(state->irq, handler, SA_SHIRQ, - "serial", &IRQ_ports[state->irq]); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } - goto errout; - } - } - - /* - * Insert serial port into IRQ chain. - */ - info->prev_port = 0; - info->next_port = IRQ_ports[state->irq]; - if (info->next_port) - info->next_port->prev_port = info; - IRQ_ports[state->irq] = info; - figure_IRQ_timeout(state->irq); - - /* - * Now, initialize the UART - */ - serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ - - info->MCR = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->MCR = UART_MCR_DTR | UART_MCR_RTS; -#ifdef CONFIG_SERIAL_MANY_PORTS - if (info->flags & ASYNC_FOURPORT) { - if (state->irq == 0) - info->MCR |= UART_MCR_OUT1; - } else -#endif - { - if (state->irq != 0) - info->MCR |= UART_MCR_OUT2; - } - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - serial_outp(info, UART_MCR, info->MCR); - - /* - * Finally, enable interrupts - */ - info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - serial_outp(info, UART_IER, info->IER); /* enable interrupts */ - -#ifdef CONFIG_SERIAL_MANY_PORTS - if (info->flags & ASYNC_FOURPORT) { - /* Enable interrupts on the AST Fourport board */ - ICP = (info->port & 0xFE0) | 0x01F; - outb_p(0x80, ICP); - (void) inb_p(ICP); - } -#endif - - /* - * And clear the interrupt registers again for luck. - */ - (void)serial_inp(info, UART_LSR); - (void)serial_inp(info, UART_RX); - (void)serial_inp(info, UART_IIR); - (void)serial_inp(info, UART_MSR); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit.head = info->xmit.tail = 0; - - /* - * Set up serial timers... - */ - mod_timer(&serial_timer, jiffies + 2*HZ/100); - - /* - * Set up the tty->alt_speed kludge - */ -#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } -#endif - - /* - * and set the speed of the serial port - */ - change_speed(info, 0); - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - -/* - * 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 shutdown(struct async_struct * info) -{ - unsigned long flags; - struct serial_state *state; - int retval; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - state = info->state; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d (irq %d)....", info->line, - state->irq); -#endif - - save_flags(flags); cli(); /* 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 - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - figure_IRQ_timeout(state->irq); - - /* - * Free the IRQ, if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, &IRQ_ports[state->irq]); - retval = request_irq(state->irq, rs_interrupt_single, - SA_SHIRQ, "serial", - &IRQ_ports[state->irq]); - - if (retval) - printk("serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, &IRQ_ports[state->irq]); - } - - if (info->xmit.buf) { - unsigned long pg = (unsigned long) info->xmit.buf; - info->xmit.buf = 0; - free_page(pg); - } - - info->IER = 0; - serial_outp(info, UART_IER, 0x00); /* disable all intrs */ -#ifdef CONFIG_SERIAL_MANY_PORTS - if (info->flags & ASYNC_FOURPORT) { - /* reset interrupts on the AST Fourport board */ - (void) inb((info->port & 0xFE0) | 0x01F); - info->MCR |= UART_MCR_OUT1; - } else -#endif - info->MCR &= ~UART_MCR_OUT2; - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - - /* disable break condition */ - serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - serial_outp(info, UART_MCR, info->MCR); - - /* disable FIFO's */ - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - -#ifdef CONFIG_SERIAL_RSA - /* - * Reset the RSA board back to 115kbps compat mode. - */ - if ((state->type == PORT_RSA) && - (state->baud_base == SERIAL_RSA_BAUD_BASE && - disable_rsa(info))) - state->baud_base = SERIAL_RSA_BAUD_BASE_LO; -#endif - - - (void)serial_in(info, UART_RX); /* read data port to reset things */ - - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - if (uart_config[info->state->type].flags & UART_STARTECH) { - /* Arrange to enter sleep mode */ - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, UART_EFR_ECB); - serial_outp(info, UART_LCR, 0); - serial_outp(info, UART_IER, UART_IERX_SLEEP); - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, 0); - serial_outp(info, UART_LCR, 0); - } - if (info->state->type == PORT_16750) { - /* Arrange to enter sleep mode */ - serial_outp(info, UART_IER, UART_IERX_SLEEP); - } - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - -#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, - 600, 1200, 1800, 2400, 4800, 9600, 19200, - 38400, 57600, 115200, 230400, 460800, 0 }; - -static int tty_get_baud_rate(struct tty_struct *tty) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned int cflag, i; - - cflag = tty->termios->c_cflag; - - i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 2) - tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - if (i == 15) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - i += 1; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - i += 2; - } - return baud_table[i]; -} -#endif - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void change_speed(struct async_struct *info, - struct termios *old_termios) -{ - int quot = 0, baud_base, baud; - unsigned cflag, cval, fcr = 0; - int bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!CONFIGURED_SERIAL_PORT(info)) - return; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: cval = 0x00; bits = 7; break; - case CS6: cval = 0x01; bits = 8; break; - case CS7: cval = 0x02; bits = 9; break; - case CS8: cval = 0x03; bits = 10; break; - /* Never happens, but GCC is too dumb to figure it out */ - default: cval = 0x00; bits = 7; break; - } - if (cflag & CSTOPB) { - cval |= 0x04; - bits++; - } - if (cflag & PARENB) { - cval |= UART_LCR_PARITY; - bits++; - } - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ -#ifdef CONFIG_SERIAL_RSA - if ((info->state->type == PORT_RSA) && - (info->state->baud_base != SERIAL_RSA_BAUD_BASE) && - enable_rsa(info)) - info->state->baud_base = SERIAL_RSA_BAUD_BASE; -#endif - baud_base = info->state->baud_base; - if (info->state->type == PORT_16C950) { - if (baud <= baud_base) - serial_icr_write(info, UART_TCR, 0); - else if (baud <= 2*baud_base) { - serial_icr_write(info, UART_TCR, 0x8); - baud_base = baud_base * 2; - } else if (baud <= 4*baud_base) { - serial_icr_write(info, UART_TCR, 0x4); - baud_base = baud_base * 4; - } else - serial_icr_write(info, UART_TCR, 0); - } - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - /* If the quotient is zero refuse the change */ - if (!quot && old_termios) { - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - } - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) - quot = baud_base / 9600; - /* - * 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) && (info->state->type == PORT_16C950) && - (info->state->revision == 0x5201)) - quot++; - - info->quot = quot; - info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - /* Set up FIFO's */ - if (uart_config[info->state->type].flags & UART_USE_FIFO) { - if ((info->state->baud_base / quot) < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; -#ifdef CONFIG_SERIAL_RSA - else if (info->state->type == PORT_RSA) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; -#endif - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; - } - if (info->state->type == PORT_16750) - fcr |= UART_FCR7_64BYTE; - - /* CTS flow control flag and modem status interrupts */ - info->IER &= ~UART_IER_MSI; - if (info->flags & ASYNC_HARDPPS_CD) - info->IER |= UART_IER_MSI; - if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; - info->IER |= UART_IER_MSI; - } else - info->flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else { - info->flags |= ASYNC_CHECK_CD; - info->IER |= UART_IER_MSI; - } - serial_out(info, UART_IER, info->IER); - - /* - * Set up parity check flag - */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (I_INPCK(info->tty)) - info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= UART_LSR_BI; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= UART_LSR_BI; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_OE; - } - /* - * !!! ignore all characters if CREAD is not set - */ - if ((cflag & CREAD) == 0) - info->ignore_status_mask |= UART_LSR_DR; - save_flags(flags); cli(); - if (uart_config[info->state->type].flags & UART_STARTECH) { - serial_outp(info, UART_LCR, 0xBF); - serial_outp(info, UART_EFR, - (cflag & CRTSCTS) ? UART_EFR_CTS : 0); - } - serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ - serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */ - serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */ - if (info->state->type == PORT_16750) - serial_outp(info, UART_FCR, fcr); /* set fcr */ - serial_outp(info, UART_LCR, cval); /* reset DLAB */ - info->LCR = cval; /* Save LCR */ - if (info->state->type != PORT_16750) { - if (fcr & UART_FCR_ENABLE_FIFO) { - /* emulated UARTs (Lucent Venus 167x) need two steps */ - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - } - serial_outp(info, UART_FCR, fcr); /* set fcr */ - } - restore_flags(flags); -} - -static void rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_put_char")) - return; - - if (!tty || !info->xmit.buf) - return; - - save_flags(flags); cli(); - if (CIRC_SPACE(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) == 0) { - restore_flags(flags); - return; - } - - info->xmit.buf[info->xmit.head] = ch; - info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); - restore_flags(flags); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) - return; - - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped - || !info->xmit.buf) - return; - - save_flags(flags); cli(); - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - restore_flags(flags); -} - -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_write")) - return 0; - - if (!tty || !info->xmit.buf || !tmp_buf) - return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); - } - if (info->xmit.head != info->xmit.tail - && !tty->stopped - && !tty->hw_stopped - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->device, "rs_write_room")) - return 0; - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) - return 0; - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) - return; - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); - wake_up_interruptible(&tty->write_wait); -#ifdef SERIAL_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->device, "rs_send_char")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->device, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) - info->MCR &= ~UART_MCR_RTS; - - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - if (tty->termios->c_cflag & CRTSCTS) - info->MCR |= UART_MCR_RTS; - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct async_struct * info, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - struct serial_state *state = info->state; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = state->type; - tmp.line = state->line; - tmp.port = state->port; - if (HIGH_BITS_OFFSET) - tmp.port_high = state->port >> HIGH_BITS_OFFSET; - else - tmp.port_high = 0; - tmp.irq = state->irq; - tmp.flags = state->flags; - tmp.xmit_fifo_size = state->xmit_fifo_size; - tmp.baud_base = state->baud_base; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - tmp.hub6 = state->hub6; - tmp.io_type = state->io_type; - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct async_struct * info, - struct serial_struct * new_info) -{ - struct serial_struct new_serial; - struct serial_state old_state, *state; - unsigned int i,change_irq,change_port; - int retval = 0; - unsigned long new_port; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - state = info->state; - old_state = *state; - - new_port = new_serial.port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - change_irq = new_serial.irq != state->irq; - change_port = (new_port != ((int) state->port)) || - (new_serial.hub6 != state->hub6); - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || - (new_serial.baud_base != state->baud_base) || - (new_serial.type != state->type) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != state->xmit_fifo_size) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - new_serial.irq = irq_cannonicalize(new_serial.irq); - - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || - (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) || - (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || - (new_serial.type == PORT_STARTECH)) { - return -EINVAL; - } - - if ((new_serial.type != state->type) || - (new_serial.xmit_fifo_size <= 0)) - new_serial.xmit_fifo_size = - uart_config[new_serial.type].dfl_xmit_fifo_size; - - /* Make sure address is not already in use */ - if (new_serial.type) { - for (i = 0 ; i < NR_PORTS; i++) - if ((state != &rs_table[i]) && - (rs_table[i].port == new_port) && - rs_table[i].type) - return -EADDRINUSE; - } - - if ((change_port || change_irq) && (state->count > 1)) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - state->baud_base = new_serial.baud_base; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; -#if (LINUX_VERSION_CODE > 0x20100) - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; -#endif - info->xmit_fifo_size = state->xmit_fifo_size = - new_serial.xmit_fifo_size; - - if ((state->type != PORT_UNKNOWN) && state->port) { -#ifdef CONFIG_SERIAL_RSA - if (old_state.type == PORT_RSA) - release_region(state->port + UART_RSA_BASE, 16); - else -#endif - release_region(state->port,8); - } - state->type = new_serial.type; - if (change_port || change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - shutdown(info); - state->irq = new_serial.irq; - info->port = state->port = new_port; - info->hub6 = state->hub6 = new_serial.hub6; - if (info->hub6) - info->io_type = state->io_type = SERIAL_IO_HUB6; - else if (info->io_type == SERIAL_IO_HUB6) - info->io_type = state->io_type = SERIAL_IO_PORT; - } - if ((state->type != PORT_UNKNOWN) && state->port) { -#ifdef CONFIG_SERIAL_RSA - if (state->type == PORT_RSA) - request_region(state->port + UART_RSA_BASE, - 16, "serial_rsa(set)"); - else -#endif - request_region(state->port,8,"serial(set)"); - } - - -check_and_exit: - if (!state->port || !state->type) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if (((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK)) || - (old_state.custom_divisor != state->custom_divisor)) { -#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; -#endif - change_speed(info, 0); - } - } else - retval = startup(info); - return retval; -} - - -/* - * 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 int get_lsr_info(struct async_struct * info, unsigned int *value) -{ - unsigned char status; - unsigned int result; - unsigned long flags; - - save_flags(flags); cli(); - status = serial_in(info, UART_LSR); - restore_flags(flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - - /* - * If we're about to load something into the transmit - * register, we'll pretend the transmitter isn't empty to - * avoid a race condition (depending on when the transmit - * interrupt happens). - */ - if (info->x_char || - ((CIRC_CNT(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) - result &= ~TIOCSER_TEMT; - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - - -static int get_modem_info(struct async_struct * info, unsigned int *value) -{ - unsigned char control, status; - unsigned int result; - unsigned long flags; - - control = info->MCR; - save_flags(flags); cli(); - status = serial_in(info, UART_MSR); - restore_flags(flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) - | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) -#ifdef TIOCM_OUT1 - | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) - | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) -#endif - | ((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); - - 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) -{ - unsigned int arg; - unsigned long flags; - - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; - - 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 - if (arg & TIOCM_LOOP) - info->MCR |= UART_MCR_LOOP; - 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 - if (arg & TIOCM_LOOP) - info->MCR &= ~UART_MCR_LOOP; - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | -#ifdef TIOCM_OUT1 - UART_MCR_OUT1 | - UART_MCR_OUT2 | -#endif - UART_MCR_LOOP | - UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) -#ifdef TIOCM_OUT1 - | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) - | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) -#endif - | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return -EINVAL; - } - save_flags(flags); cli(); - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - return 0; -} - -static int do_autoconfig(struct async_struct * info) -{ - int irq, retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (info->state->count > 1) - return -EBUSY; - - shutdown(info); - - autoconfig(info->state); - if ((info->state->flags & ASYNC_AUTO_IRQ) && - (info->state->port != 0 || info->state->iomem_base != 0) && - (info->state->type != PORT_UNKNOWN)) { - irq = detect_uart_irq(info->state); - if (irq > 0) - info->state->irq = irq; - } - - retval = startup(info); - if (retval) - return retval; - return 0; -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ -static void send_break( struct async_struct * info, int duration) -{ - if (!CONFIGURED_SERIAL_PORT(info)) - return; - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + duration; - cli(); - info->LCR |= UART_LCR_SBC; - serial_out(info, UART_LCR, info->LCR); - schedule(); - info->LCR &= ~UART_LCR_SBC; - serial_out(info, UART_LCR, info->LCR); - sti(); -} -#else -static void rs_break(struct tty_struct *tty, int break_state) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->device, "rs_break")) - return; - - if (!CONFIGURED_SERIAL_PORT(info)) - return; - save_flags(flags); cli(); - if (break_state == -1) - info->LCR |= UART_LCR_SBC; - else - info->LCR &= ~UART_LCR_SBC; - serial_out(info, UART_LCR, info->LCR); - restore_flags(flags); -} -#endif - -#ifdef CONFIG_SERIAL_MULTIPORT -static int get_multiport_struct(struct async_struct * info, - struct serial_multiport_struct *retinfo) -{ - struct serial_multiport_struct ret; - struct rs_multiport_struct *multi; - - multi = &rs_multiport[info->state->irq]; - - ret.port_monitor = multi->port_monitor; - - ret.port1 = multi->port1; - ret.mask1 = multi->mask1; - ret.match1 = multi->match1; - - ret.port2 = multi->port2; - ret.mask2 = multi->mask2; - ret.match2 = multi->match2; - - ret.port3 = multi->port3; - ret.mask3 = multi->mask3; - ret.match3 = multi->match3; - - ret.port4 = multi->port4; - ret.mask4 = multi->mask4; - ret.match4 = multi->match4; - - ret.irq = info->state->irq; - - if (copy_to_user(retinfo,&ret,sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_multiport_struct(struct async_struct * info, - struct serial_multiport_struct *in_multi) -{ - struct serial_multiport_struct new_multi; - struct rs_multiport_struct *multi; - struct serial_state *state; - int was_multi, now_multi; - int retval; - void (*handler)(int, void *, struct pt_regs *); - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - state = info->state; - - if (copy_from_user(&new_multi, in_multi, - sizeof(struct serial_multiport_struct))) - return -EFAULT; - - if (new_multi.irq != state->irq || state->irq == 0 || - !IRQ_ports[state->irq]) - return -EINVAL; - - multi = &rs_multiport[state->irq]; - was_multi = (multi->port1 != 0); - - multi->port_monitor = new_multi.port_monitor; - - if (multi->port1) - release_region(multi->port1,1); - multi->port1 = new_multi.port1; - multi->mask1 = new_multi.mask1; - multi->match1 = new_multi.match1; - if (multi->port1) - request_region(multi->port1,1,"serial(multiport1)"); - - if (multi->port2) - release_region(multi->port2,1); - multi->port2 = new_multi.port2; - multi->mask2 = new_multi.mask2; - multi->match2 = new_multi.match2; - if (multi->port2) - request_region(multi->port2,1,"serial(multiport2)"); - - if (multi->port3) - release_region(multi->port3,1); - multi->port3 = new_multi.port3; - multi->mask3 = new_multi.mask3; - multi->match3 = new_multi.match3; - if (multi->port3) - request_region(multi->port3,1,"serial(multiport3)"); - - if (multi->port4) - release_region(multi->port4,1); - multi->port4 = new_multi.port4; - multi->mask4 = new_multi.mask4; - multi->match4 = new_multi.match4; - if (multi->port4) - request_region(multi->port4,1,"serial(multiport4)"); - - now_multi = (multi->port1 != 0); - - if (IRQ_ports[state->irq]->next_port && - (was_multi != now_multi)) { - free_irq(state->irq, &IRQ_ports[state->irq]); - if (now_multi) - handler = rs_interrupt_multi; - else - handler = rs_interrupt; - - retval = request_irq(state->irq, handler, SA_SHIRQ, - "serial", &IRQ_ports[state->irq]); - if (retval) { - printk("Couldn't reallocate serial interrupt " - "driver!!\n"); - } - } - return 0; -} -#endif - -static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct icount; - unsigned long flags; -#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ - int retval, tmp; -#endif - - if (serial_paranoia_check(info, tty->device, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { -#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */ - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (signal_pending(current)) - return -EINTR; - if (!arg) { - send_break(info, HZ/4); /* 1/4 second */ - if (signal_pending(current)) - return -EINTR; - } - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (signal_pending(current)) - return -EINTR; - send_break(info, arg ? arg*(HZ/10) : HZ/4); - if (signal_pending(current)) - return -EINTR; - return 0; - case TIOCGSOFTCAR: - tmp = C_CLOCAL(tty) ? 1 : 0; - if (copy_to_user((void *)arg, &tmp, sizeof(int))) - return -EFAULT; - return 0; - case TIOCSSOFTCAR: - if (copy_from_user(&tmp, (void *)arg, sizeof(int))) - return -EFAULT; - - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (tmp ? CLOCAL : 0)); - return 0; -#endif - 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); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERCONFIG: - return do_autoconfig(info); - - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct))) - return -EFAULT; - return 0; - -#ifdef CONFIG_SERIAL_MULTIPORT - case TIOCSERGETMULTI: - return get_multiport_struct(info, - (struct serial_multiport_struct *) arg); - case TIOCSERSETMULTI: - return set_multiport_struct(info, - (struct serial_multiport_struct *) arg); -#endif - - /* - * 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 for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - save_flags(flags); cli(); - /* note the counters on entry */ - cprev = info->state->icount; - restore_flags(flags); - /* Force modem status interrupts on */ - info->IER |= UART_IER_MSI; - serial_out(info, UART_IER, info->IER); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - save_flags(flags); cli(); - cnow = info->state->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - save_flags(flags); cli(); - cnow = info->state->icount; - restore_flags(flags); - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - if (copy_to_user((void *)arg, &icount, sizeof(icount))) - return -EFAULT; - return 0; - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - if ( (cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - - change_speed(info, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { - info->MCR |= UART_MCR_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->MCR |= UART_MCR_RTS; - } - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } - -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->device, "rs_close")) - return; - - state = info->state; - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, state->count); -#endif - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); - state->count = 0; - } - if (state->count) { - DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - restore_flags(flags); - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ASYNC_NORMAL_ACTIVE) - info->state->normal_termios = *tty->termios; - if (info->flags & ASYNC_CALLOUT_ACTIVE) - info->state->callout_termios = *tty->termios; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->IER &= ~UART_IER_RLSI; - info->read_status_mask &= ~UART_LSR_DR; - if (info->flags & ASYNC_INITIALIZED) { - serial_out(info, UART_IER, info->IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - rs_wait_until_sent(tty, info->timeout); - } - shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - info->event = 0; - info->tty = 0; - if (info->blocked_open) { - if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| - ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long orig_jiffies, char_time; - int lsr; - - if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) - return; - - if (info->state->type == PORT_UNKNOWN) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2*info->timeout) - timeout = 2*info->timeout; -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); -#endif - while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) { -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...", lsr, jiffies); -#endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -#endif -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rs_hangup(struct tty_struct *tty) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; - - if (serial_paranoia_check(info, tty->device, "rs_hangup")) - return; - - state = info->state; - - rs_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) - return; - shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct async_struct *info) -{ - DECLARE_WAITQUEUE(wait, current); - struct serial_state *state = info->state; - int retval; - int do_clocal = 0, extra_count = 0; - unsigned long flags; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { - if (info->flags & ASYNC_NORMAL_ACTIVE) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_SESSION_LOCKOUT) && - (info->session != current->session)) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)) - return -EBUSY; - info->flags |= ASYNC_CALLOUT_ACTIVE; - return 0; - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (info->flags & ASYNC_CALLOUT_ACTIVE) { - if (state->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 - * this loop, state->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttys%d, count = %d\n", - state->line, state->count); -#endif - save_flags(flags); cli(); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - restore_flags(flags); - info->blocked_open++; - while (1) { - save_flags(flags); cli(); - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - (tty->termios->c_cflag & CBAUD)) - serial_out(info, UART_MCR, - serial_inp(info, UART_MCR) | - (UART_MCR_DTR | UART_MCR_RTS)); - restore_flags(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ASYNC_CLOSING) && - (do_clocal || (serial_in(info, UART_MSR) & - UART_MSR_DCD))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - info = sstate->info; - - /* - * If the async_struct is already allocated, do the fastpath. - */ - if (info) - goto out; - - info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } - - memset(info, 0, sizeof(struct async_struct)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->magic = SERIAL_MAGIC; - info->port = sstate->port; - info->hub6 = sstate->hub6; - info->flags = sstate->flags; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->state = sstate; - info->line = line; - info->iomem_base = sstate->iomem_base; - info->iomem_reg_shift = sstate->iomem_reg_shift; - info->io_type = sstate->io_type; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - - if (sstate->info) { - kfree(info); - info = sstate->info; - } else { - sstate->info = info; - } - -out: - /* - * If this is the first open, copy over some timeouts. - */ - if (sstate->count == 1) { - info->closing_wait = sstate->closing_wait; - } - *ret_info = info; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int rs_open(struct tty_struct *tty, struct file * filp) -{ - struct async_struct *info; - int retval, line; - unsigned long page; - - MOD_INC_USE_COUNT; - line = minor(tty->device) - tty->driver.minor_start; - if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - retval = get_async_struct(line, &info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->device, "rs_open")) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, - info->state->count); -#endif -#if (LINUX_VERSION_CODE > 0x20100) - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; -#endif - - /* - * This relies on lock_kernel() stuff so wants tidying for 2.5 - */ - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - MOD_DEC_USE_COUNT; -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open returning after block_til_ready with %d\n", - retval); -#endif - MOD_DEC_USE_COUNT; - return retval; - } - - if ((info->state->count == 1) && - (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->state->normal_termios; - else - *tty->termios = info->state->callout_termios; - change_speed(info, 0); - } -#ifdef CONFIG_SERIAL_CONSOLE - if (sercons.cflag && sercons.index == line) { - tty->termios->c_cflag = sercons.cflag; - sercons.cflag = 0; - change_speed(info, 0); - } -#endif - info->session = current->session; - info->pgrp = current->pgrp; - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttys%d successful...", info->line); -#endif - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline int line_info(char *buf, struct serial_state *state) -{ - struct async_struct *info = state->info, scr_info; - char stat_buf[30], control, status; - int ret; - unsigned long flags; - - ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", - state->line, uart_config[state->type].name, - state->port, state->irq); - - if (!state->port || (state->type == PORT_UNKNOWN)) { - ret += sprintf(buf+ret, "\n"); - return ret; - } - - /* - * Figure out the current RS-232 lines - */ - if (!info) { - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->port = state->port; - info->flags = state->flags; - info->hub6 = state->hub6; - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - info->quot = 0; - info->tty = 0; - } - save_flags(flags); cli(); - status = serial_in(info, UART_MSR); - control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR); - restore_flags(flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (control & UART_MCR_RTS) - strcat(stat_buf, "|RTS"); - if (status & UART_MSR_CTS) - strcat(stat_buf, "|CTS"); - if (control & UART_MCR_DTR) - strcat(stat_buf, "|DTR"); - if (status & UART_MSR_DSR) - strcat(stat_buf, "|DSR"); - if (status & UART_MSR_DCD) - strcat(stat_buf, "|CD"); - if (status & UART_MSR_RI) - strcat(stat_buf, "|RI"); - - if (info->quot) { - ret += sprintf(buf+ret, " baud:%d", - state->baud_base / info->quot); - } - - ret += sprintf(buf+ret, " tx:%d rx:%d", - state->icount.tx, state->icount.rx); - - if (state->icount.frame) - ret += sprintf(buf+ret, " fe:%d", state->icount.frame); - - if (state->icount.parity) - ret += sprintf(buf+ret, " pe:%d", state->icount.parity); - - if (state->icount.brk) - ret += sprintf(buf+ret, " brk:%d", state->icount.brk); - - if (state->icount.overrun) - ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); - - /* - * Last thing is the RS-232 status lines - */ - ret += sprintf(buf+ret, " %s\n", stat_buf+1); - return ret; -} - -int rs_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - int i, len = 0, l; - off_t begin = 0; - - len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n", - serial_version, LOCAL_VERSTRING, serial_revdate); - for (i = 0; i < NR_PORTS && len < 4000; i++) { - l = line_info(page + len, &rs_table[i]); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } - } - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static char serial_options[] __initdata = -#ifdef CONFIG_HUB6 - " HUB-6" -#define SERIAL_OPT -#endif -#ifdef CONFIG_SERIAL_MANY_PORTS - " MANY_PORTS" -#define SERIAL_OPT -#endif -#ifdef CONFIG_SERIAL_MULTIPORT - " MULTIPORT" -#define SERIAL_OPT -#endif -#ifdef CONFIG_SERIAL_SHARE_IRQ - " SHARE_IRQ" -#define SERIAL_OPT -#endif -#ifdef CONFIG_SERIAL_DETECT_IRQ - " DETECT_IRQ" -#define SERIAL_OPT -#endif -#ifdef ENABLE_SERIAL_PCI - " SERIAL_PCI" -#define SERIAL_OPT -#endif -#ifdef ENABLE_SERIAL_PNP - " ISAPNP" -#define SERIAL_OPT -#endif -#ifdef ENABLE_SERIAL_ACPI - " SERIAL_ACPI" -#define SERIAL_OPT -#endif -#ifdef SERIAL_OPT - " enabled\n"; -#else - " no serial options enabled\n"; -#endif -#undef SERIAL_OPT - -static _INLINE_ void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name, - serial_version, LOCAL_VERSTRING, serial_revdate, - serial_options); -} - -/* - * This routine detect the IRQ of a serial port by clearing OUT2 when - * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at - * each time, as long as no other device permanently request the IRQ. - * If no IRQ is detected, or multiple IRQ appear, this function returns 0. - * The variable "state" and the field "state->port" should not be null. - */ -static unsigned detect_uart_irq (struct serial_state * state) -{ - int irq; - unsigned long irqs; - unsigned char save_mcr, save_ier; - struct async_struct scr_info; /* serial_{in,out} because HUB6 */ - -#ifdef CONFIG_SERIAL_MANY_PORTS - unsigned char save_ICP=0; /* no warning */ - unsigned short ICP=0; - - if (state->flags & ASYNC_FOURPORT) { - ICP = (state->port & 0xFE0) | 0x01F; - save_ICP = inb_p(ICP); - outb_p(0x80, ICP); - (void) inb_p(ICP); - } -#endif - scr_info.magic = SERIAL_MAGIC; - scr_info.state = state; - scr_info.port = state->port; - scr_info.flags = state->flags; -#ifdef CONFIG_HUB6 - scr_info.hub6 = state->hub6; -#endif - scr_info.io_type = state->io_type; - scr_info.iomem_base = state->iomem_base; - scr_info.iomem_reg_shift = state->iomem_reg_shift; - - /* forget possible initially masked and pending IRQ */ - probe_irq_off(probe_irq_on()); - save_mcr = serial_inp(&scr_info, UART_MCR); - save_ier = serial_inp(&scr_info, UART_IER); - serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); - - irqs = probe_irq_on(); - serial_outp(&scr_info, UART_MCR, 0); - udelay (10); - if (state->flags & ASYNC_FOURPORT) { - serial_outp(&scr_info, UART_MCR, - UART_MCR_DTR | UART_MCR_RTS); - } else { - serial_outp(&scr_info, UART_MCR, - UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); - } - serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */ - (void)serial_inp(&scr_info, UART_LSR); - (void)serial_inp(&scr_info, UART_RX); - (void)serial_inp(&scr_info, UART_IIR); - (void)serial_inp(&scr_info, UART_MSR); - serial_outp(&scr_info, UART_TX, 0xFF); - udelay (20); - irq = probe_irq_off(irqs); - - serial_outp(&scr_info, UART_MCR, save_mcr); - serial_outp(&scr_info, UART_IER, save_ier); -#ifdef CONFIG_SERIAL_MANY_PORTS - if (state->flags & ASYNC_FOURPORT) - outb_p(save_ICP, ICP); -#endif - return (irq > 0)? irq : 0; -} - -/* - * This is a quickie test to see how big the FIFO is. - * It doesn't work at all the time, more's the pity. - */ -static int size_fifo(struct async_struct *info) -{ - unsigned char old_fcr, old_mcr, old_dll, old_dlm; - int count; - - old_fcr = serial_inp(info, UART_FCR); - old_mcr = serial_inp(info, UART_MCR); - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); - serial_outp(info, UART_MCR, UART_MCR_LOOP); - serial_outp(info, UART_LCR, UART_LCR_DLAB); - old_dll = serial_inp(info, UART_DLL); - old_dlm = serial_inp(info, UART_DLM); - serial_outp(info, UART_DLL, 0x01); - serial_outp(info, UART_DLM, 0x00); - serial_outp(info, UART_LCR, 0x03); - for (count = 0; count < 256; count++) - serial_outp(info, UART_TX, count); - mdelay(20); - for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) && - (count < 256); count++) - serial_inp(info, UART_RX); - serial_outp(info, UART_FCR, old_fcr); - serial_outp(info, UART_MCR, old_mcr); - serial_outp(info, UART_LCR, UART_LCR_DLAB); - serial_outp(info, UART_DLL, old_dll); - serial_outp(info, UART_DLM, old_dlm); - - return count; -} - -/* - * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. - * When this function is called we know it is at least a StarTech - * 16650 V2, but it might be one of several StarTech UARTs, or one of - * its clones. (We treat the broken original StarTech 16650 V1 as a - * 16550, and why not? Startech doesn't seem to even acknowledge its - * existence.) - * - * What evil have men's minds wrought... - */ -static void autoconfig_startech_uarts(struct async_struct *info, - struct serial_state *state, - unsigned long flags) -{ - unsigned char scratch, scratch2, scratch3, scratch4; - - /* - * First we check to see if it's an Oxford Semiconductor UART. - * - * If we have to do this here because some non-National - * Semiconductor clone chips lock up if you try writing to the - * LSR register (which serial_icr_read does) - */ - if (state->type == PORT_16550A) { - /* - * EFR [4] must be set else this test fails - * - * This shouldn't be necessary, but Mike Hudson - * (Exoray@isys.ca) claims that it's needed for 952 - * dual UART's (which are not recommended for new designs). - */ - info->ACR = 0; - serial_out(info, UART_LCR, 0xBF); - serial_out(info, UART_EFR, 0x10); - serial_out(info, UART_LCR, 0x00); - /* Check for Oxford Semiconductor 16C950 */ - scratch = serial_icr_read(info, UART_ID1); - scratch2 = serial_icr_read(info, UART_ID2); - scratch3 = serial_icr_read(info, UART_ID3); - - if (scratch == 0x16 && scratch2 == 0xC9 && - (scratch3 == 0x50 || scratch3 == 0x52 || - scratch3 == 0x54)) { - state->type = PORT_16C950; - state->revision = serial_icr_read(info, UART_REV) | - (scratch3 << 8); - return; - } - } - - /* - * We check for a XR16C850 by setting DLL and DLM to 0, and - * then reading back DLL and DLM. If DLM reads back 0x10, - * then the UART is a XR16C850 and the DLL contains the chip - * revision. If DLM reads back 0x14, then the UART is a - * XR16C854. - * - */ - - /* Save the DLL and DLM */ - - serial_outp(info, UART_LCR, UART_LCR_DLAB); - scratch3 = serial_inp(info, UART_DLL); - scratch4 = serial_inp(info, UART_DLM); - - serial_outp(info, UART_DLL, 0); - serial_outp(info, UART_DLM, 0); - scratch2 = serial_inp(info, UART_DLL); - scratch = serial_inp(info, UART_DLM); - serial_outp(info, UART_LCR, 0); - - if (scratch == 0x10 || scratch == 0x14) { - if (scratch == 0x10) - state->revision = scratch2; - state->type = PORT_16850; - return; - } - - /* Restore the DLL and DLM */ - - serial_outp(info, UART_LCR, UART_LCR_DLAB); - serial_outp(info, UART_DLL, scratch3); - serial_outp(info, UART_DLM, scratch4); - serial_outp(info, UART_LCR, 0); - /* - * We distinguish between the '654 and the '650 by counting - * how many bytes are in the FIFO. I'm using this for now, - * since that's the technique that was sent to me in the - * serial driver update, but I'm not convinced this works. - * I've had problems doing this in the past. -TYT - */ - if (size_fifo(info) == 64) - state->type = PORT_16654; - else - state->type = PORT_16650V2; -} - -/* - * 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 serial_state * state) -{ - unsigned char status1, status2, scratch, scratch2, scratch3; - unsigned char save_lcr, save_mcr; - struct async_struct *info, scr_info; - unsigned long flags; - - state->type = PORT_UNKNOWN; - -#ifdef SERIAL_DEBUG_AUTOCONF - printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, - state->port, (unsigned) state->iomem_base); -#endif - - if (!CONFIGURED_SERIAL_PORT(state)) - return; - - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->state = state; - info->port = state->port; - info->flags = state->flags; -#ifdef CONFIG_HUB6 - info->hub6 = state->hub6; -#endif - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - - save_flags(flags); cli(); - - if (!(state->flags & ASYNC_BUGGY_UART) && - !state->iomem_base) { - /* - * Do a simple existence test first; if we fail this, - * there's no point trying anything else. - * - * 0x80 is used as a nonsense port to prevent against - * false positives due to ISA bus float. The - * assumption is that 0x80 is a non-existent port; - * which should be safe since include/asm/io.h also - * makes this assumption. - */ - scratch = serial_inp(info, UART_IER); - serial_outp(info, UART_IER, 0); -#ifdef __i386__ - outb(0xff, 0x080); -#endif - scratch2 = serial_inp(info, UART_IER); - serial_outp(info, UART_IER, 0x0F); -#ifdef __i386__ - outb(0, 0x080); -#endif - scratch3 = serial_inp(info, UART_IER); - serial_outp(info, UART_IER, scratch); - if (scratch2 || scratch3 != 0x0F) { -#ifdef SERIAL_DEBUG_AUTOCONF - printk("serial: ttyS%d: simple autoconfig failed " - "(%02x, %02x)\n", state->line, - scratch2, scratch3); -#endif - restore_flags(flags); - return; /* We failed; there's nothing here */ - } - } - - save_mcr = serial_in(info, UART_MCR); - save_lcr = serial_in(info, UART_LCR); - - /* - * Check to see if a UART is really there. Certain broken - * internal modems based on the Rockwell chipset fail this - * test, because they apparently don't implement the loopback - * test mode. So this test is skipped on the COM 1 through - * COM 4 ports. This *should* be safe, since no board - * manufacturer would be stupid enough to design a board - * that conflicts with COM 1-4 --- we hope! - */ - if (!(state->flags & ASYNC_SKIP_TEST)) { - serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A); - status1 = serial_inp(info, UART_MSR) & 0xF0; - serial_outp(info, UART_MCR, save_mcr); - if (status1 != 0x90) { -#ifdef SERIAL_DEBUG_AUTOCONF - printk("serial: ttyS%d: no UART loopback failed\n", - state->line); -#endif - restore_flags(flags); - return; - } - } - serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */ - serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ - serial_outp(info, UART_LCR, 0); - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - scratch = serial_in(info, UART_IIR) >> 6; - switch (scratch) { - case 0: - state->type = PORT_16450; - break; - case 1: - state->type = PORT_UNKNOWN; - break; - case 2: - state->type = PORT_16550; - break; - case 3: - state->type = PORT_16550A; - break; - } - if (state->type == PORT_16550A) { - /* Check for Startech UART's */ - serial_outp(info, UART_LCR, UART_LCR_DLAB); - if (serial_in(info, UART_EFR) == 0) { - state->type = PORT_16650; - } else { - serial_outp(info, UART_LCR, 0xBF); - if (serial_in(info, UART_EFR) == 0) - autoconfig_startech_uarts(info, state, flags); - } - } - if (state->type == PORT_16550A) { - /* Check for TI 16750 */ - serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB); - serial_outp(info, UART_FCR, - UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); - scratch = serial_in(info, UART_IIR) >> 5; - if (scratch == 7) { - /* - * If this is a 16750, and not a cheap UART - * clone, then it should only go into 64 byte - * mode if the UART_FCR7_64BYTE bit was set - * while UART_LCR_DLAB was latched. - */ - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(info, UART_LCR, 0); - serial_outp(info, UART_FCR, - UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); - scratch = serial_in(info, UART_IIR) >> 5; - if (scratch == 6) - state->type = PORT_16750; - } - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - } -#if defined(CONFIG_SERIAL_RSA) && defined(MODULE) - if (state->type == PORT_16550A) { - int i; - - for (i = 0 ; i < PORT_RSA_MAX ; ++i) { - if (!probe_rsa[i] && !force_rsa[i]) - break; - if (((probe_rsa[i] != state->port) || - check_region(state->port + UART_RSA_BASE, 16)) && - (force_rsa[i] != state->port)) - continue; - if (!enable_rsa(info)) - continue; - state->type = PORT_RSA; - state->baud_base = SERIAL_RSA_BAUD_BASE; - break; - } - } -#endif - serial_outp(info, UART_LCR, save_lcr); - if (state->type == PORT_16450) { - scratch = serial_in(info, UART_SCR); - serial_outp(info, UART_SCR, 0xa5); - status1 = serial_in(info, UART_SCR); - serial_outp(info, UART_SCR, 0x5a); - status2 = serial_in(info, UART_SCR); - serial_outp(info, UART_SCR, scratch); - - if ((status1 != 0xa5) || (status2 != 0x5a)) - state->type = PORT_8250; - } - state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; - - if (state->type == PORT_UNKNOWN) { - restore_flags(flags); - return; - } - - if (info->port) { -#ifdef CONFIG_SERIAL_RSA - if (state->type == PORT_RSA) - request_region(info->port + UART_RSA_BASE, 16, - "serial_rsa(auto)"); - else -#endif - request_region(info->port,8,"serial(auto)"); - } - - /* - * Reset the UART. - */ -#ifdef CONFIG_SERIAL_RSA - if (state->type == PORT_RSA) - serial_outp(info, UART_RSA_FRR, 0); -#endif - serial_outp(info, UART_MCR, save_mcr); - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - (void)serial_in(info, UART_RX); - serial_outp(info, UART_IER, 0); - - restore_flags(flags); -} - -int register_serial(struct serial_struct *req); -void unregister_serial(int line); - -#if (LINUX_VERSION_CODE > 0x20100) -EXPORT_SYMBOL(register_serial); -EXPORT_SYMBOL(unregister_serial); -#else -static struct symbol_table serial_syms = { -#include - X(register_serial), - X(unregister_serial), -#include -}; -#endif - - -#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) - -static void __devinit printk_pnp_dev_id(unsigned short vendor, - unsigned short device) -{ - printk("%c%c%c%x%x%x%x", - 'A' + ((vendor >> 2) & 0x3f) - 1, - 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, - 'A' + ((vendor >> 8) & 0x1f) - 1, - (device >> 4) & 0x0f, - device & 0x0f, - (device >> 12) & 0x0f, - (device >> 8) & 0x0f); -} - -static _INLINE_ int get_pci_port(struct pci_dev *dev, - struct pci_board *board, - struct serial_struct *req, - int idx) -{ - unsigned long port; - int base_idx; - int max_port; - int offset; - - base_idx = SPCI_FL_GET_BASE(board->flags); - if (board->flags & SPCI_FL_BASE_TABLE) - base_idx += idx; - - if (board->flags & SPCI_FL_REGION_SZ_CAP) { - max_port = pci_resource_len(dev, base_idx) / 8; - if (idx >= max_port) - return 1; - } - - offset = board->first_uart_offset; - - /* Timedia/SUNIX uses a mixture of BARs and offsets */ - /* Ugh, this is ugly as all hell --- TYT */ - if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */ - switch(idx) { - case 0: base_idx=0; - break; - case 1: base_idx=0; offset=8; - break; - case 2: base_idx=1; - break; - case 3: base_idx=1; offset=8; - break; - case 4: /* BAR 2*/ - case 5: /* BAR 3 */ - case 6: /* BAR 4*/ - case 7: base_idx=idx-2; /* BAR 5*/ - } - - /* Some Titan cards are also a little weird */ - if (dev->vendor == PCI_VENDOR_ID_TITAN && - (dev->device == PCI_DEVICE_ID_TITAN_400L || - dev->device == PCI_DEVICE_ID_TITAN_800L)) { - switch (idx) { - case 0: base_idx = 1; - break; - case 1: base_idx = 2; - break; - default: - base_idx = 4; - offset = 8 * (idx - 2); - } - - } - - port = pci_resource_start(dev, base_idx) + offset; - - if ((board->flags & SPCI_FL_BASE_TABLE) == 0) - port += idx * (board->uart_offset ? board->uart_offset : 8); - - if (IS_PCI_REGION_IOPORT(dev, base_idx)) { - req->port = port; - if (HIGH_BITS_OFFSET) - req->port_high = port >> HIGH_BITS_OFFSET; - else - req->port_high = 0; - return 0; - } - req->io_type = SERIAL_IO_MEM; - req->iomem_base = ioremap(port, board->uart_offset); - req->iomem_reg_shift = board->reg_shift; - req->port = 0; - return 0; -} - -static _INLINE_ int get_pci_irq(struct pci_dev *dev, - struct pci_board *board, - int idx) -{ - int base_idx; - - if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) - return dev->irq; - - base_idx = SPCI_FL_GET_IRQBASE(board->flags); - if (board->flags & SPCI_FL_IRQ_TABLE) - base_idx += idx; - - return PCI_IRQ_RESOURCE(dev, base_idx); -} - -/* - * Common enabler code shared by both PCI and ISAPNP probes - */ -static void __devinit start_pci_pnp_board(struct pci_dev *dev, - struct pci_board *board) -{ - int k, line; - struct serial_struct serial_req; - int base_baud; - - if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) { - printk("serial: PNP device '"); - printk_pnp_dev_id(dev->vendor, dev->device); - printk("' prepare failed\n"); - return; - } - - if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) { - printk("serial: PNP device '"); - printk_pnp_dev_id(dev->vendor, dev->device); - printk("' activate failed\n"); - return; - } - - /* - * Run the initialization function, if any - */ - if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0)) - return; - - /* - * Register the serial board in the array if we need to - * shutdown the board on a module unload or card removal - */ - if (DEACTIVATE_FUNC(dev) || board->init_fn) { - for (k=0; k < NR_PCI_BOARDS; k++) - if (serial_pci_board[k].dev == 0) - break; - if (k >= NR_PCI_BOARDS) - return; - serial_pci_board[k].board = *board; - serial_pci_board[k].dev = dev; - } - - base_baud = board->base_baud; - if (!base_baud) - base_baud = BASE_BAUD; - memset(&serial_req, 0, sizeof(serial_req)); - - for (k=0; k < board->num_ports; k++) { - serial_req.irq = get_pci_irq(dev, board, k); - if (get_pci_port(dev, board, &serial_req, k)) - break; - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; -#ifdef SERIAL_DEBUG_PCI - printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", - serial_req.port, serial_req.irq, serial_req.io_type); -#endif - line = register_serial(&serial_req); - if (line < 0) - break; - rs_table[line].baud_base = base_baud; - rs_table[line].dev = dev; - } -} -#endif /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */ - -#ifdef ENABLE_SERIAL_PCI -/* - * Some PCI serial cards using the PLX 9050 PCI interface chip require - * that the card interrupt be explicitly enabled or disabled. This - * seems to be mainly needed on card using the PLX which also use I/O - * mapped memory. - */ -static int __devinit -pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) -{ - u8 data, *p, irq_config; - int pci_config; - - irq_config = 0x41; - pci_config = PCI_COMMAND_MEMORY; - if (dev->vendor == PCI_VENDOR_ID_PANACOM) - irq_config = 0x43; - if ((dev->vendor == PCI_VENDOR_ID_PLX) && - (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { - /* - * As the megawolf cards have the int pins active - * high, and have 2 UART chips, both ints must be - * enabled on the 9050. Also, the UARTS are set in - * 16450 mode by default, so we have to enable the - * 16C950 'enhanced' mode so that we can use the deep - * FIFOs - */ - irq_config = 0x5b; - pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO; - } - - pci_read_config_byte(dev, PCI_COMMAND, &data); - - if (enable) - pci_write_config_byte(dev, PCI_COMMAND, - data | pci_config); - - /* enable/disable interrupts */ - p = ioremap(pci_resource_start(dev, 0), 0x80); - writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c); - iounmap(p); - - if (!enable) - pci_write_config_byte(dev, PCI_COMMAND, - data & ~pci_config); - return 0; -} - - -/* - * SIIG serial cards have an PCI interface chip which also controls - * the UART clocking frequency. Each UART can be clocked independently - * (except cards equiped with 4 UARTs) and initial clocking settings - * are stored in the EEPROM chip. It can cause problems because this - * version of serial driver doesn't support differently clocked UART's - * on single PCI card. To prevent this, initialization functions set - * high frequency clocking for all UART's on given card. It is safe (I - * hope) because it doesn't touch EEPROM settings to prevent conflicts - * with other OSes (like M$ DOS). - * - * SIIG support added by Andrey Panin , 10/1999 - * - * There is two family of SIIG serial cards with different PCI - * interface chip and different configuration methods: - * - 10x cards have control registers in IO and/or memory space; - * - 20x cards have control registers in standard PCI configuration space. - */ - -#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) -#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) - -static int __devinit -pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable) -{ - u16 data, *p; - - if (!enable) return 0; - - p = ioremap(pci_resource_start(dev, 0), 0x80); - - switch (dev->device & 0xfff8) { - case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ - data = 0xffdf; - break; - case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ - data = 0xf7ff; - break; - default: /* 1S1P, 4S */ - data = 0xfffb; - break; - } - - writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); - iounmap(p); - return 0; -} - -#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) -#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) - -static int __devinit -pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable) -{ - u8 data; - - if (!enable) return 0; - - /* Change clock frequency for the first UART. */ - pci_read_config_byte(dev, 0x6f, &data); - pci_write_config_byte(dev, 0x6f, data & 0xef); - - /* If this card has 2 UART, we have to do the same with second UART. */ - if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) || - ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) { - pci_read_config_byte(dev, 0x73, &data); - pci_write_config_byte(dev, 0x73, data & 0xef); - } - return 0; -} - -/* Added for EKF Intel i960 serial boards */ -static int __devinit -pci_inteli960ni_fn(struct pci_dev *dev, - struct pci_board *board, - int enable) -{ - unsigned long oldval; - - if (!(pci_get_subdevice(dev) & 0x1000)) - return(-1); - - if (!enable) /* is there something to deinit? */ - return(0); - -#ifdef SERIAL_DEBUG_PCI - printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n", - (unsigned long) board->subdevice); -#endif - /* is firmware started? */ - pci_read_config_dword(dev, 0x44, (void*) &oldval); - if (oldval == 0x00001000L) { /* RESET value */ - printk(KERN_DEBUG "Local i960 firmware missing"); - return(-1); - } - return(0); -} - -/* - * Timedia has an explosion of boards, and to avoid the PCI table from - * growing *huge*, we use this function to collapse some 70 entries - * in the PCI table into one, for sanity's and compactness's sake. - */ -static unsigned short timedia_single_port[] = { - 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; -static unsigned short timedia_dual_port[] = { - 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, - 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, - 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, - 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, - 0xD079, 0 }; -static unsigned short timedia_quad_port[] = { - 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, - 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, - 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, - 0xB157, 0 }; -static unsigned short timedia_eight_port[] = { - 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, - 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; -static struct timedia_struct { - int num; - unsigned short *ids; -} timedia_data[] = { - { 1, timedia_single_port }, - { 2, timedia_dual_port }, - { 4, timedia_quad_port }, - { 8, timedia_eight_port }, - { 0, 0 } -}; - -static int __devinit -pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable) -{ - int i, j; - unsigned short *ids; - - if (!enable) - return 0; - - for (i=0; timedia_data[i].num; i++) { - ids = timedia_data[i].ids; - for (j=0; ids[j]; j++) { - if (pci_get_subdevice(dev) == ids[j]) { - board->num_ports = timedia_data[i].num; - return 0; - } - } - } - return 0; -} - -static int __devinit -pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - return 0; -} - -/* - * This is the configuration table for all of the PCI serial boards - * which we support. It is directly indexed by the pci_board_num_t enum - * value, which is encoded in the pci_device_id PCI probe table's - * driver_data member. - */ -enum pci_board_num_t { - pbn_b0_1_115200, - pbn_default = 0, - - pbn_b0_2_115200, - pbn_b0_4_115200, - - pbn_b0_1_921600, - pbn_b0_2_921600, - pbn_b0_4_921600, - - pbn_b0_bt_1_115200, - pbn_b0_bt_2_115200, - pbn_b0_bt_1_460800, - pbn_b0_bt_2_460800, - - pbn_b1_1_115200, - pbn_b1_2_115200, - pbn_b1_4_115200, - pbn_b1_8_115200, - - pbn_b1_2_921600, - pbn_b1_4_921600, - pbn_b1_8_921600, - - pbn_b1_2_1382400, - pbn_b1_4_1382400, - pbn_b1_8_1382400, - - pbn_b2_8_115200, - pbn_b2_4_460800, - pbn_b2_8_460800, - pbn_b2_16_460800, - pbn_b2_4_921600, - pbn_b2_8_921600, - - pbn_b2_bt_1_115200, - pbn_b2_bt_2_115200, - pbn_b2_bt_4_115200, - pbn_b2_bt_2_921600, - - pbn_panacom, - pbn_panacom2, - pbn_panacom4, - pbn_plx_romulus, - pbn_oxsemi, - pbn_timedia, - pbn_intel_i960, - pbn_sgi_ioc3, -#ifdef CONFIG_DDB5074 - pbn_nec_nile4, -#endif -#if 0 - pbn_dci_pccom8, -#endif - pbn_xircom_combo, - - pbn_siig10x_0, - pbn_siig10x_1, - pbn_siig10x_2, - pbn_siig10x_4, - pbn_siig20x_0, - pbn_siig20x_2, - pbn_siig20x_4, - - pbn_computone_4, - pbn_computone_6, - pbn_computone_8, -}; - -static struct pci_board pci_boards[] __devinitdata = { - /* - * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, - * Offset to get to next UART's registers, - * Register shift to use for memory-mapped I/O, - * Initialization function, first UART offset - */ - - /* Generic serial board, pbn_b0_1_115200, pbn_default */ - { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, - pbn_default */ - - { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ - { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ - - { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ - { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ - { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ - - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ - - { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ - { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ - { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ - { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ - - { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ - { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ - { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ - - { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ - { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ - { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ - - { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ - { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ - { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ - { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ - { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ - { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ - - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ - - { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ - 0x20, 2, pci_plx9050_fn, 0x03 }, - /* This board uses the size of PCI Base region 0 to - * signal now many ports are available */ - { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ - { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ - 0, 0, pci_timedia_fn }, - /* EKF addition for i960 Boards form EKF with serial port */ - { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ - 8<<2, 2, pci_inteli960ni_fn, 0x10000}, - { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ - 1, 458333, 0, 0, 0, 0x20178 }, -#ifdef CONFIG_DDB5074 - /* - * NEC Vrc-5074 (Nile 4) builtin UART. - * Conditionally compiled in since this is a motherboard device. - */ - { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ - 64, 3, NULL, 0x300 }, -#endif -#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ /* pbn_dci_pccom8 */ - { SPCI_FL_BASE3, 8, 115200, 8 }, -#endif - { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ - 0, 0, pci_xircom_fn }, - - { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ - 0, 0, pci_siig20x_fn }, - - { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ - 0x40, 2, NULL, 0x200 }, -}; - -/* - * Given a complete unknown PCI device, try to use some heuristics to - * guess what the configuration might be, based on the pitiful PCI - * serial specs. Returns 0 on success, 1 on failure. - */ -static int __devinit serial_pci_guess_board(struct pci_dev *dev, - struct pci_board *board) -{ - int num_iomem = 0, num_port = 0, first_port = -1; - int i; - - /* - * If it is not a communications device or the programming - * interface is greater than 6, give up. - * - * (Should we try to make guesses for multiport serial devices - * later?) - */ - if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) && - ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) || - (dev->class & 0xff) > 6) - return 1; - - for (i=0; i < 6; i++) { - if (IS_PCI_REGION_IOPORT(dev, i)) { - num_port++; - if (first_port == -1) - first_port = i; - } - if (IS_PCI_REGION_IOMEM(dev, i)) - num_iomem++; - } - - /* - * If there is 1 or 0 iomem regions, and exactly one port, use - * it. - */ - if (num_iomem <= 1 && num_port == 1) { - board->flags = first_port; - return 0; - } - return 1; -} - -static int __devinit serial_init_one(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - struct pci_board *board, tmp; - int rc; - - board = &pci_boards[ent->driver_data]; - - rc = pci_enable_device(dev); - if (rc) return rc; - - if (ent->driver_data == pbn_default && - serial_pci_guess_board(dev, board)) - return -ENODEV; - else if (serial_pci_guess_board(dev, &tmp) == 0) { - printk(KERN_INFO "Redundant entry in serial pci_table. " - "Please send the output of\n" - "lspci -vv, this message (%04x,%04x,%04x,%04x)\n" - "and the manufacturer and name of " - "serial board or modem board\n" - "to serial-pci-info@lists.sourceforge.net.\n", - dev->vendor, dev->device, - pci_get_subvendor(dev), pci_get_subdevice(dev)); - } - - start_pci_pnp_board(dev, board); - - return 0; -} - -static void __devexit serial_remove_one(struct pci_dev *dev) -{ - int i; - - /* - * Iterate through all of the ports finding those that belong - * to this PCI device. - */ - for(i = 0; i < NR_PORTS; i++) { - if (rs_table[i].dev != dev) - continue; - unregister_serial(i); - rs_table[i].dev = 0; - } - /* - * Now execute any board-specific shutdown procedure - */ - for (i=0; i < NR_PCI_BOARDS; i++) { - struct pci_board_inst *brd = &serial_pci_board[i]; - - if (serial_pci_board[i].dev != dev) - continue; - if (brd->board.init_fn) - (brd->board.init_fn)(brd->dev, &brd->board, 0); - if (DEACTIVATE_FUNC(brd->dev)) - (DEACTIVATE_FUNC(brd->dev))(brd->dev); - serial_pci_board[i].dev = 0; - } -} - - -static struct pci_device_id serial_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, - pbn_b1_8_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, - pbn_b1_4_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, - pbn_b1_2_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, - pbn_b1_8_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, - pbn_b1_4_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, - pbn_b1_2_1382400 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0, - pbn_b1_8_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0, - pbn_b1_8_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0, - pbn_b1_4_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0, - pbn_b1_4_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0, - pbn_b1_2_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0, - pbn_b1_8_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0, - pbn_b1_8_921600 }, - { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, - PCI_SUBVENDOR_ID_CONNECT_TECH, - PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, - pbn_b1_4_921600 }, - - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_1_115200 }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_2_115200 }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_4_115200 }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_2_115200 }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_4_115200 }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_8_115200 }, - - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_2_115200 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_2_921600 }, - /* VScom SPCOM800, from sl@s.pl */ - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_8_921600 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_4_921600 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_KEYSPAN, - PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, - pbn_panacom }, - { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_panacom4 }, - { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_panacom2 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIFAST, - PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, - pbn_b2_4_460800 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIFAST, - PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, - pbn_b2_8_460800 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIFAST, - PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, - pbn_b2_16_460800 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIFAST, - PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, - pbn_b2_16_460800 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIRAS, - PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, - pbn_b2_4_460800 }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_SUBVENDOR_ID_CHASE_PCIRAS, - PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, - pbn_b2_8_460800 }, - /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ - /* (Exoray@isys.ca) */ - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, - 0x10b5, 0x106a, 0, 0, - pbn_plx_romulus }, - { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b1_4_115200 }, - { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b1_2_115200 }, - { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b1_8_115200 }, - { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b1_8_115200 }, - { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, - PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, - pbn_b0_4_921600 }, - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - 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 }, - - /* Digitan DS560-558, from jimd@esoft.com */ - { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b1_1_115200 }, - - /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ - { PCI_VENDOR_ID_USR, 0x1008, - PCI_ANY_ID, PCI_ANY_ID, }, - - /* Titan Electronic cards */ - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_2_921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_4_921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_4_921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1, 1, 921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, - /* The 400L and 800L have a custom hack in get_pci_port */ - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 4, 921600 }, - { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 8, 921600 }, - - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, - - /* Computone devices submitted by Doug McNash dmcnash@computone.com */ - { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, - PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, - 0, 0, pbn_computone_4 }, - { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, - PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8, - 0, 0, pbn_computone_8 }, - { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, - PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6, - 0, 0, pbn_computone_6 }, - - { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, - { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, - PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, - - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_460800 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_460800 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_460800 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_1_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_1_460800 }, - - /* RAStel 2 port modem, gerg@moreton.com.au */ - { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b2_bt_2_115200 }, - - /* EKF addition for i960 Boards form EKF with serial port */ - { PCI_VENDOR_ID_INTEL, 0x1960, - 0xE4BF, PCI_ANY_ID, 0, 0, - pbn_intel_i960 }, - - /* Xircom Cardbus/Ethernet combos */ - { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_xircom_combo }, - - /* - * Untested PCI modems, sent in from various folks... - */ - - /* Elsa Model 56K PCI Modem, from Andreas Rath */ - { PCI_VENDOR_ID_ROCKWELL, 0x1004, - 0x1048, 0x1500, 0, 0, - pbn_b1_1_115200 }, - - { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, - 0xFF00, 0, 0, 0, - pbn_sgi_ioc3 }, - -#ifdef CONFIG_DDB5074 - /* - * NEC Vrc-5074 (Nile 4) builtin UART. - * Conditionally compiled in since this is a motherboard device. - */ - { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_nec_nile4 }, -#endif - -#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */ - { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_dci_pccom8 }, -#endif - - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, }, - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, serial_pci_tbl); - -static struct pci_driver serial_pci_driver = { - name: "serial", - probe: serial_init_one, - remove: __devexit_p(serial_remove_one), - id_table: serial_pci_tbl, -}; - - -/* - * Query PCI space for known serial boards - * If found, add them to the PCI device space in rs_table[] - * - * Accept a maximum of eight boards - * - */ -static void __devinit probe_serial_pci(void) -{ -#ifdef SERIAL_DEBUG_PCI - printk(KERN_DEBUG "Entered probe_serial_pci()\n"); -#endif - - /* Register call PCI serial devices. Null out - * the driver name upon failure, as a signal - * not to attempt to unregister the driver later - */ - if (pci_module_init (&serial_pci_driver) != 0) - serial_pci_driver.name = ""; - -#ifdef SERIAL_DEBUG_PCI - printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n"); -#endif - return; -} - -#endif /* ENABLE_SERIAL_PCI */ - -#ifdef ENABLE_SERIAL_PNP - -struct pnp_board { - unsigned short vendor; - unsigned short device; -}; - -static struct pnp_board pnp_devices[] __devinitdata = { - /* Archtek America Corp. */ - /* Archtek SmartLink Modem 3334BT Plug & Play */ - { ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, - /* Anchor Datacomm BV */ - /* SXPro 144 External Data Fax Modem Plug & Play */ - { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) }, - /* SXPro 288 External Data Fax Modem Plug & Play */ - { ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) }, - /* Rockwell 56K ACF II Fax+Data+Voice Modem */ - { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) }, - /* AZT3005 PnP SOUND DEVICE */ - { ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) }, - /* Best Data Products Inc. Smart One 336F PnP Modem */ - { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, - /* Boca Research */ - /* Boca Complete Ofc Communicator 14.4 Data-FAX */ - { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, - /* Boca Research 33,600 ACF Modem */ - { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) }, - /* Boca 33.6 Kbps Internal FD34FSVD */ - { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) }, - /* Boca 33.6 Kbps Internal FD34FSVD */ - { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) }, - /* Best Data Products Inc. Smart One 336F PnP Modem */ - { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) }, - /* Computer Peripherals Inc */ - /* EuroViVa CommCenter-33.6 SP PnP */ - { ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) }, - /* Creative Labs */ - /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ - { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) }, - /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ - { ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) }, - /* Creative */ - /* Creative Modem Blaster Flash56 DI5601-1 */ - { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) }, - /* Creative Modem Blaster V.90 DI5660 */ - { ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) }, - /* FUJITSU */ - /* Fujitsu 33600 PnP-I2 R Plug & Play */ - { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) }, - /* Fujitsu FMV-FX431 Plug & Play */ - { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) }, - /* Fujitsu 33600 PnP-I4 R Plug & Play */ - { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) }, - /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */ - { ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) }, - /* Archtek America Corp. */ - /* Archtek SmartLink Modem 3334BT Plug & Play */ - { ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) }, - /* Hayes */ - /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) }, - /* Hayes Optima 336 V.34 + FAX + Voice PnP */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) }, - /* Hayes Optima 336B V.34 + FAX + Voice PnP */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) }, - /* Hayes Accura 56K Ext Fax Modem PnP */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) }, - /* Hayes Accura 56K Ext Fax Modem PnP */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) }, - /* Hayes Accura 56K Fax Modem PnP */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) }, - /* Hayes 288, V.34 + FAX */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) }, - /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */ - { ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) }, - /* IBM */ - /* IBM Thinkpad 701 Internal Modem Voice */ - { ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) }, - /* Intertex */ - /* Intertex 28k8 33k6 Voice EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) }, - /* Intertex 33k6 56k Voice EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) }, - /* Intertex 28k8 33k6 Voice SP EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) }, - /* Intertex 33k6 56k Voice SP EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) }, - /* Intertex 28k8 33k6 Voice SP INT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) }, - /* Intertex 28k8 33k6 Voice SP EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) }, - /* Intertex 33k6 56k Voice SP EXT PnP */ - { ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) }, - /* Kortex International */ - /* KORTEX 28800 Externe PnP */ - { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) }, - /* KXPro 33.6 Vocal ASVD PnP */ - { ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) }, - /* Lasat */ - /* LASAT Internet 33600 PnP */ - { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) }, - /* Lasat Safire 560 PnP */ - { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) }, - /* Lasat Safire 336 PnP */ - { ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) }, - /* Microcom, Inc. */ - /* Microcom TravelPorte FAST V.34 Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) }, - /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) }, - /* Microcom DeskPorte FAST EP 28.8 Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) }, - /* Microcom DeskPorte 28.8P Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) }, - /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, - /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, - /* Microcom DeskPorte 28.8S Internal Plug & Play */ - { ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) }, - /* Motorola */ - /* Motorola BitSURFR Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) }, - /* Motorola TA210 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) }, - /* Motorola HMTA 200 (ISDN) Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) }, - /* Motorola BitSURFR Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) }, - /* Motorola Lifestyle 28.8 Internal */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) }, - /* Motorola V.3400 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) }, - /* Motorola Lifestyle 28.8 V.34 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) }, - /* Motorola Power 28.8 V.34 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) }, - /* Motorola ModemSURFR External 28.8 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) }, - /* Motorola Premier 33.6 Desktop Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) }, - /* Motorola VoiceSURFR 56K External PnP */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) }, - /* Motorola ModemSURFR 56K External PnP */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) }, - /* Motorola ModemSURFR 56K Internal PnP */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) }, - /* Motorola ModemSURFR Internal 28.8 Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) }, - /* Motorola Premier 33.6 Internal Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) }, - /* Motorola OnlineSURFR 28.8 Internal Plug & Play */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) }, - /* Motorola VoiceSURFR 56K Internal PnP */ - { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) }, - /* Com 1 */ - /* Deskline K56 Phone System PnP */ - { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) }, - /* PC Rider K56 Phone System PnP */ - { ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) }, - /* Pace 56 Voice Internal Plug & Play Modem */ - { ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) }, - /* Generic */ - /* Generic standard PC COM port */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) }, - /* Generic 16550A-compatible COM port */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) }, - /* Compaq 14400 Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) }, - /* Compaq 2400/9600 Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) }, - /* Dial-Up Networking Serial Cable between 2 PCs */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) }, - /* Dial-Up Networking Parallel Cable between 2 PCs */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) }, - /* Standard 9600 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) }, - /* Standard 14400 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) }, - /* Standard 28800 bps Modem*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) }, - /* Standard Modem*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) }, - /* Standard 9600 bps Modem*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) }, - /* Standard 14400 bps Modem*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) }, - /* Standard 28800 bps Modem*/ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) }, - /* Standard Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) }, - /* Standard 9600 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) }, - /* Standard 14400 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) }, - /* Standard 28800 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) }, - /* Standard Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) }, - /* Standard 9600 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) }, - /* Standard 14400 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) }, - /* Standard 28800 bps Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) }, - /* Standard Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) }, - /* Standard PCMCIA Card Modem */ - { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) }, - /* Rockwell */ - /* Modular Technology */ - /* Rockwell 33.6 DPF Internal PnP */ - /* Modular Technology 33.6 Internal PnP */ - { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) }, - /* Kortex International */ - /* KORTEX 14400 Externe PnP */ - { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) }, - /* Viking Components, Inc */ - /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */ - { ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) }, - /* Rockwell */ - /* British Telecom */ - /* Modular Technology */ - /* Rockwell 33.6 DPF External PnP */ - /* BT Prologue 33.6 External PnP */ - /* Modular Technology 33.6 External PnP */ - { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) }, - /* Viking 56K FAX INT */ - { ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) }, - /* SupraExpress 28.8 Data/Fax PnP modem */ - { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) }, - /* SupraExpress 33.6 Data/Fax PnP modem */ - { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) }, - /* SupraExpress 33.6 Data/Fax PnP modem */ - { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) }, - /* SupraExpress 33.6 Data/Fax PnP modem */ - { ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) }, - /* Phoebe Micro */ - /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ - { ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) }, - /* Archtek America Corp. */ - /* Archtek SmartLink Modem 3334BT Plug & Play */ - { ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) }, - /* 3Com Corp. */ - /* Gateway Telepath IIvi 33.6 */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) }, - /* Sportster Vi 14.4 PnP FAX Voicemail */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) }, - /* U.S. Robotics 33.6K Voice INT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) }, - /* U.S. Robotics 33.6K Voice EXT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) }, - /* U.S. Robotics 33.6K Voice INT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) }, - /* U.S. Robotics 56K Voice INT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) }, - /* U.S. Robotics 56K Voice EXT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) }, - /* U.S. Robotics 56K FAX INT */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) }, - /* U.S. Robotics 56K Voice INT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) }, - /* U.S. Robotics 56K Voice EXT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) }, - /* U.S. Robotics 56K Voice INT PnP */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) }, - /* U.S. Robotics 56K Message */ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) }, - /* U.S. Robotics 56K FAX EXT PnP*/ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) }, - /* U.S. Robotics 56K FAX INT PnP*/ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) }, - /* U.S. Robotics 56K Voice EXT PnP*/ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) }, - /* U.S. Robotics 56K Voice INT PnP*/ - { ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) }, - { 0, } -}; - -static void inline avoid_irq_share(struct pci_dev *dev) -{ - int i; - unsigned long map = 0x1FF8; - struct serial_state *state = rs_table; - struct isapnp_irq *irq; - struct isapnp_resources *res = dev->sysdata; - - for (i = 0; i < NR_PORTS; i++) { - if (state->type != PORT_UNKNOWN) - clear_bit(state->irq, &map); - state++; - } - - for ( ; res; res = res->alt) - for(irq = res->irq; irq; irq = irq->next) - irq->map = map; -} - -static char *modem_names[] __devinitdata = { - "MODEM", "Modem", "modem", "FAX", "Fax", "fax", - "56K", "56k", "K56", "33.6", "28.8", "14.4", - "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", - "33600", "28800", "14400", "V.90", "V.34", "V.32", 0 -}; - -static int __devinit check_name(char *name) -{ - char **tmp = modem_names; - - while (*tmp) { - if (strstr(name, *tmp)) - return 1; - tmp++; - } - return 0; -} - -static int inline check_compatible_id(struct pci_dev *dev) -{ - int i; - for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++) - if ((dev->vendor_compatible[i] == - ISAPNP_VENDOR('P', 'N', 'P')) && - (swab16(dev->device_compatible[i]) >= 0xc000) && - (swab16(dev->device_compatible[i]) <= 0xdfff)) - return 0; - return 1; -} - -/* - * Given a complete unknown ISA PnP device, try to use some heuristics to - * detect modems. Currently use such heuristic set: - * - dev->name or dev->bus->name must contain "modem" substring; - * - device must have only one IO region (8 byte long) with base adress - * 0x2e8, 0x3e8, 0x2f8 or 0x3f8. - * - * Such detection looks very ugly, but can detect at least some of numerous - * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] - * table. - */ -static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev, - struct pci_board *board) -{ - struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; - struct isapnp_resources *resa; - - if (!(check_name(dev->name) || check_name(dev->bus->name)) && - !(check_compatible_id(dev))) - return 1; - - if (!res || res->next) - return 1; - - for (resa = res->alt; resa; resa = resa->alt) { - struct isapnp_port *port; - for (port = res->port; port; port = port->next) - if ((port->size == 8) && - ((port->min == 0x2f8) || - (port->min == 0x3f8) || - (port->min == 0x2e8) || - (port->min == 0x3e8))) - return 0; - } - - return 1; -} - -static void __devinit probe_serial_pnp(void) -{ - struct pci_dev *dev = NULL; - struct pnp_board *pnp_board; - struct pci_board board; - -#ifdef SERIAL_DEBUG_PNP - printk("Entered probe_serial_pnp()\n"); -#endif - if (!isapnp_present()) { -#ifdef SERIAL_DEBUG_PNP - printk("Leaving probe_serial_pnp() (no isapnp)\n"); -#endif - return; - } - - isapnp_for_each_dev(dev) { - if (dev->active) - continue; - - memset(&board, 0, sizeof(board)); - board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT; - board.num_ports = 1; - board.base_baud = 115200; - - for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++) - if ((dev->vendor == pnp_board->vendor) && - (dev->device == pnp_board->device)) - break; - - if (pnp_board->vendor) { - /* Special case that's more efficient to hardcode */ - if ((pnp_board->vendor == ISAPNP_VENDOR('A', 'K', 'Y') && - pnp_board->device == ISAPNP_DEVICE(0x1021))) - board.flags |= SPCI_FL_NO_SHIRQ; - } else { - if (serial_pnp_guess_board(dev, &board)) - continue; - } - - if (board.flags & SPCI_FL_NO_SHIRQ) - avoid_irq_share(dev); - start_pci_pnp_board(dev, &board); - } - -#ifdef SERIAL_DEBUG_PNP - printk("Leaving probe_serial_pnp() (probe finished)\n"); -#endif - return; -} - -#endif /* ENABLE_SERIAL_PNP */ - -/* - * The serial driver boot-time initialization code! - */ -static int __init rs_init(void) -{ - int i; - struct serial_state * state; - - init_bh(SERIAL_BH, do_serial_bh); - init_timer(&serial_timer); - serial_timer.function = rs_timer; - mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); - - for (i = 0; i < NR_IRQS; i++) { - IRQ_ports[i] = 0; - IRQ_timeout[i] = 0; -#ifdef CONFIG_SERIAL_MULTIPORT - memset(&rs_multiport[i], 0, - sizeof(struct rs_multiport_struct)); -#endif - } -#ifdef CONFIG_SERIAL_CONSOLE - /* - * The interrupt of the serial console port - * can't be shared. - */ - if (sercons.flags & CON_CONSDEV) { - for(i = 0; i < NR_PORTS; i++) - if (i != sercons.index && - rs_table[i].irq == rs_table[sercons.index].irq) - rs_table[i].irq = 0; - } -#endif - show_serial_version(); - - /* Initialize the tty_driver structure */ - - memset(&serial_driver, 0, sizeof(struct tty_driver)); - serial_driver.magic = TTY_DRIVER_MAGIC; -#if (LINUX_VERSION_CODE > 0x20100) - serial_driver.driver_name = "serial"; -#endif -#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) - serial_driver.name = "tts/%d"; -#else - serial_driver.name = "ttyS"; -#endif - serial_driver.major = TTY_MAJOR; - serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET; - serial_driver.num = NR_PORTS; - serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - serial_driver.subtype = SERIAL_TYPE_NORMAL; - serial_driver.init_termios = tty_std_termios; - serial_driver.init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - serial_driver.refcount = &serial_refcount; - serial_driver.table = serial_table; - serial_driver.termios = serial_termios; - serial_driver.termios_locked = serial_termios_locked; - - serial_driver.open = rs_open; - serial_driver.close = rs_close; - serial_driver.write = rs_write; - serial_driver.put_char = rs_put_char; - serial_driver.flush_chars = rs_flush_chars; - serial_driver.write_room = rs_write_room; - serial_driver.chars_in_buffer = rs_chars_in_buffer; - serial_driver.flush_buffer = rs_flush_buffer; - serial_driver.ioctl = rs_ioctl; - serial_driver.throttle = rs_throttle; - serial_driver.unthrottle = rs_unthrottle; - serial_driver.set_termios = rs_set_termios; - serial_driver.stop = rs_stop; - serial_driver.start = rs_start; - serial_driver.hangup = rs_hangup; -#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - serial_driver.break_ctl = rs_break; -#endif -#if (LINUX_VERSION_CODE >= 131343) - serial_driver.send_xchar = rs_send_xchar; - serial_driver.wait_until_sent = rs_wait_until_sent; - serial_driver.read_proc = rs_read_proc; -#endif - - /* - * The callout device is just like normal device except for - * major number and the subtype code. - */ - callout_driver = serial_driver; -#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) - callout_driver.name = "cua/%d"; -#else - callout_driver.name = "cua"; -#endif - callout_driver.major = TTYAUX_MAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; -#if (LINUX_VERSION_CODE >= 131343) - callout_driver.read_proc = 0; - callout_driver.proc_entry = 0; -#endif - - if (tty_register_driver(&serial_driver)) - panic("Couldn't register serial driver\n"); - if (tty_register_driver(&callout_driver)) - panic("Couldn't register callout driver\n"); - - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - state->magic = SSTATE_MAGIC; - state->line = i; - state->type = PORT_UNKNOWN; - state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; - state->callout_termios = callout_driver.init_termios; - state->normal_termios = serial_driver.init_termios; - state->icount.cts = state->icount.dsr = - state->icount.rng = state->icount.dcd = 0; - state->icount.rx = state->icount.tx = 0; - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - state->irq = irq_cannonicalize(state->irq); - if (state->hub6) - state->io_type = SERIAL_IO_HUB6; - if (state->port && check_region(state->port,8)) - continue; -#ifdef CONFIG_MCA - if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus) - continue; -#endif - if (state->flags & ASYNC_BOOT_AUTOCONF) - autoconfig(state); - } - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - if (state->type == PORT_UNKNOWN) - continue; - if ( (state->flags & ASYNC_BOOT_AUTOCONF) - && (state->flags & ASYNC_AUTO_IRQ) - && (state->port != 0 || state->iomem_base != 0)) - state->irq = detect_uart_irq(state); - if (state->io_type == SERIAL_IO_MEM) { - printk(KERN_INFO"ttyS%02d%s at 0x%px (irq = %d) is a %s\n", - state->line + SERIAL_DEV_OFFSET, - (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", - state->iomem_base, state->irq, - uart_config[state->type].name); - } - else { - printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", - state->line + SERIAL_DEV_OFFSET, - (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", - state->port, state->irq, - uart_config[state->type].name); - } - tty_register_devfs(&serial_driver, 0, - serial_driver.minor_start + state->line); - tty_register_devfs(&callout_driver, 0, - callout_driver.minor_start + state->line); - } -#ifdef ENABLE_SERIAL_PCI - probe_serial_pci(); -#endif -#ifdef ENABLE_SERIAL_PNP - probe_serial_pnp(); -#endif - return 0; -} - -/* - * This is for use by architectures that know their serial console - * attributes only at run time. Not to be invoked after rs_init(). - */ -int __init early_serial_setup(struct serial_struct *req) -{ - int i = req->line; - - if (i >= NR_IRQS) - return(-ENOENT); - rs_table[i].magic = 0; - rs_table[i].baud_base = req->baud_base; - rs_table[i].port = req->port; - if (HIGH_BITS_OFFSET) - rs_table[i].port += (unsigned long) req->port_high << - HIGH_BITS_OFFSET; - rs_table[i].irq = req->irq; - rs_table[i].flags = req->flags; - rs_table[i].close_delay = req->close_delay; - rs_table[i].io_type = req->io_type; - rs_table[i].hub6 = req->hub6; - rs_table[i].iomem_base = req->iomem_base; - rs_table[i].iomem_reg_shift = req->iomem_reg_shift; - rs_table[i].type = req->type; - rs_table[i].xmit_fifo_size = req->xmit_fifo_size; - rs_table[i].custom_divisor = req->custom_divisor; - rs_table[i].closing_wait = req->closing_wait; - return(0); -} - -/* - * register_serial and unregister_serial allows for 16x50 serial ports to be - * configured at run-time, to support PCMCIA modems. - */ - -/** - * 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 neccessary 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) -{ - int i; - unsigned long flags; - struct serial_state *state; - struct async_struct *info; - unsigned long port; - - port = req->port; - if (HIGH_BITS_OFFSET) - port += (unsigned long) req->port_high << HIGH_BITS_OFFSET; - - save_flags(flags); cli(); - for (i = 0; i < NR_PORTS; i++) { - if ((rs_table[i].port == port) && - (rs_table[i].iomem_base == req->iomem_base)) - break; - } -#ifdef __i386__ - if (i == NR_PORTS) { - for (i = 4; i < NR_PORTS; i++) - if ((rs_table[i].type == PORT_UNKNOWN) && - (rs_table[i].count == 0)) - break; - } -#endif - if (i == NR_PORTS) { - for (i = 0; i < NR_PORTS; i++) - if ((rs_table[i].type == PORT_UNKNOWN) && - (rs_table[i].count == 0)) - break; - } - if (i == NR_PORTS) { - restore_flags(flags); - return -1; - } - state = &rs_table[i]; - if (rs_table[i].count) { - restore_flags(flags); - printk("Couldn't configure serial #%d (port=%ld,irq=%d): " - "device already open\n", i, port, req->irq); - return -1; - } - state->irq = req->irq; - state->port = port; - state->flags = req->flags; - state->io_type = req->io_type; - state->iomem_base = req->iomem_base; - state->iomem_reg_shift = req->iomem_reg_shift; - if (req->baud_base) - state->baud_base = req->baud_base; - if ((info = state->info) != NULL) { - info->port = port; - info->flags = req->flags; - info->io_type = req->io_type; - info->iomem_base = req->iomem_base; - info->iomem_reg_shift = req->iomem_reg_shift; - } - autoconfig(state); - if (state->type == PORT_UNKNOWN) { - restore_flags(flags); - printk("register_serial(): autoconfig failed\n"); - return -1; - } - restore_flags(flags); - - if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state)) - state->irq = detect_uart_irq(state); - - printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", - state->line + SERIAL_DEV_OFFSET, - state->iomem_base ? "iomem" : "port", - state->iomem_base ? (unsigned long)state->iomem_base : - state->port, state->irq, uart_config[state->type].name); - tty_register_devfs(&serial_driver, 0, - serial_driver.minor_start + state->line); - tty_register_devfs(&callout_driver, 0, - callout_driver.minor_start + state->line); - return state->line + SERIAL_DEV_OFFSET; -} - -/** - * unregister_serial - deconfigure a 16x50 serial port - * @line: line to deconfigure - * - * The port specified is deconfigured and its resources are freed. Any - * user of the port is disconnected as if carrier was dropped. Line is - * the port number returned by register_serial(). - */ - -void unregister_serial(int line) -{ - unsigned long flags; - struct serial_state *state = &rs_table[line]; - - save_flags(flags); cli(); - if (state->info && state->info->tty) - tty_hangup(state->info->tty); - state->type = PORT_UNKNOWN; - printk(KERN_INFO "ttyS%02d unloaded\n", state->line); - /* These will be hidden, because they are devices that will no longer - * be available to the system. (ie, PCMCIA modems, once ejected) - */ - tty_unregister_devfs(&serial_driver, - serial_driver.minor_start + state->line); - tty_unregister_devfs(&callout_driver, - callout_driver.minor_start + state->line); - restore_flags(flags); -} - -static void __exit rs_fini(void) -{ - unsigned long flags; - int e1, e2; - int i; - struct async_struct *info; - - /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - del_timer_sync(&serial_timer); - save_flags(flags); cli(); - remove_bh(SERIAL_BH); - if ((e1 = tty_unregister_driver(&serial_driver))) - printk("serial: failed to unregister serial driver (%d)\n", - e1); - if ((e2 = tty_unregister_driver(&callout_driver))) - printk("serial: failed to unregister callout driver (%d)\n", - e2); - restore_flags(flags); - - for (i = 0; i < NR_PORTS; i++) { - if ((info = rs_table[i].info)) { - rs_table[i].info = NULL; - kfree(info); - } - if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { -#ifdef CONFIG_SERIAL_RSA - if (rs_table[i].type == PORT_RSA) - release_region(rs_table[i].port + - UART_RSA_BASE, 16); - else -#endif - release_region(rs_table[i].port, 8); - } -#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) - if (rs_table[i].iomem_base) - iounmap(rs_table[i].iomem_base); -#endif - } -#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) - for (i=0; i < NR_PCI_BOARDS; i++) { - struct pci_board_inst *brd = &serial_pci_board[i]; - - if (serial_pci_board[i].dev == 0) - continue; - if (brd->board.init_fn) - (brd->board.init_fn)(brd->dev, &brd->board, 0); - if (DEACTIVATE_FUNC(brd->dev)) - (DEACTIVATE_FUNC(brd->dev))(brd->dev); - } -#endif - if (tmp_buf) { - unsigned long pg = (unsigned long) tmp_buf; - tmp_buf = NULL; - free_page(pg); - } - -#ifdef ENABLE_SERIAL_PCI - if (serial_pci_driver.name[0]) - pci_unregister_driver (&serial_pci_driver); -#endif -} - -module_init(rs_init); -module_exit(rs_fini); -MODULE_DESCRIPTION("Standard/generic (dumb) serial driver"); -MODULE_AUTHOR("Theodore Ts'o "); -MODULE_LICENSE("GPL"); - - -/* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ - */ -#ifdef CONFIG_SERIAL_CONSOLE - -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - -static struct async_struct async_sercons; - -/* - * Wait for transmitter & holding register to empty - */ -static inline void wait_for_xmitr(struct async_struct *info) -{ - unsigned int status, tmout = 1000000; - - do { - status = serial_in(info, UART_LSR); - - if (status & UART_LSR_BI) - lsr_break_flag = UART_LSR_BI; - - if (--tmout == 0) - break; - } while((status & BOTH_EMPTY) != BOTH_EMPTY); - - /* Wait for flow control if necessary */ - if (info->flags & ASYNC_CONS_FLOW) { - tmout = 1000000; - while (--tmout && - ((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0)); - } -} - - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console must be locked when we get here. - */ -static void serial_console_write(struct console *co, const char *s, - unsigned count) -{ - static struct async_struct *info = &async_sercons; - int ier; - unsigned i; - - /* - * First save the IER then disable the interrupts - */ - ier = serial_in(info, UART_IER); - serial_out(info, UART_IER, 0x00); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(info); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(info, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(info); - serial_out(info, UART_TX, 13); - } - } - - /* - * Finally, Wait for transmitter & holding register to empty - * and restore the IER - */ - wait_for_xmitr(info); - serial_out(info, UART_IER, ier); -} - -static kdev_t serial_console_device(struct console *c) -{ - return mk_kdev(TTY_MAJOR, 64 + c->index); -} - -/* - * Setup initial baud/bits/parity/flow control. We do two things here: - * - construct a cflag setting for the first rs_open() - * - initialize the serial port - * Return non-zero if we didn't find a serial port. - */ -static int __init serial_console_setup(struct console *co, char *options) -{ - static struct async_struct *info; - struct serial_state *state; - unsigned cval; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int doflow = 0; - int cflag = CREAD | HUPCL | CLOCAL; - int quot = 0; - char *s; - - if (options) { - baud = simple_strtoul(options, NULL, 10); - s = options; - while(*s >= '0' && *s <= '9') - s++; - if (*s) parity = *s++; - if (*s) bits = *s++ - '0'; - if (*s) doflow = (*s++ == 'r'); - } - - /* - * Now construct a cflag setting. - */ - switch(baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - /* - * Set this to a sane value to prevent a divide error - */ - baud = 9600; - break; - } - switch(bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; - } - switch(parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; - } - co->cflag = cflag; - - /* - * Divisor, bytesize and parity - */ - state = rs_table + co->index; - if (doflow) - state->flags |= ASYNC_CONS_FLOW; - info = &async_sercons; - info->magic = SERIAL_MAGIC; - info->state = state; - info->port = state->port; - info->flags = state->flags; -#ifdef CONFIG_HUB6 - info->hub6 = state->hub6; -#endif - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - quot = state->baud_base / baud; - cval = cflag & (CSIZE | CSTOPB); -#if defined(__powerpc__) || defined(__alpha__) - cval >>= 8; -#else /* !__powerpc__ && !__alpha__ */ - cval >>= 4; -#endif /* !__powerpc__ && !__alpha__ */ - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; - - /* - * Disable UART interrupts, set DTR and RTS high - * and set speed. - */ - serial_out(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ - serial_out(info, UART_DLL, quot & 0xff); /* LS of divisor */ - serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */ - serial_out(info, UART_LCR, cval); /* reset DLAB */ - serial_out(info, UART_IER, 0); - serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); - - /* - * If we read 0xff from the LSR, there is no UART here. - */ - if (serial_in(info, UART_LSR) == 0xff) - return -1; - - return 0; -} - -static struct console sercons = { - name: "ttyS", - write: serial_console_write, - device: serial_console_device, - setup: serial_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -/* - * Register console. - */ -void __init serial_console_init(void) -{ - register_console(&sercons); -} -#endif - -/* - Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" - End: -*/ diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/serial167.c Wed Jul 24 14:03:38 2002 @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -236,8 +237,8 @@ } static inline int -serial_paranoia_check(struct cyclades_port *info, - dev_t device, const char *routine) +serial_paranoia_check(struct cyclades_port *info, kdev_t device, + const char *routine) { #ifdef SERIAL_PARANOIA_CHECK static const char *badmagic = @@ -1261,7 +1262,7 @@ break; } - cli(); + save_flags(flags); cli(); c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); @@ -1276,7 +1277,7 @@ up(&tmp_buf_sem); } else { while (1) { - cli(); + save_flags(flags); cli(); c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) { @@ -1376,7 +1377,7 @@ #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), + printk("throttle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); printk("cy_throttle ttyS%d\n", info->line); #endif @@ -1412,7 +1413,7 @@ #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - printk("throttle %s: %d....\n", _tty_name(tty, buf), + printk("throttle %s: %d....\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); printk("cy_unthrottle ttyS%d\n", info->line); #endif @@ -2394,7 +2395,11 @@ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; +#ifdef CONFIG_DEVFS_FS + cy_serial_driver.name = "tts/%d"; +#else cy_serial_driver.name = "ttyS"; +#endif cy_serial_driver.major = TTY_MAJOR; cy_serial_driver.minor_start = 64; cy_serial_driver.num = NR_PORTS; @@ -2429,7 +2434,11 @@ * major number and the subtype code. */ cy_callout_driver = cy_serial_driver; +#ifdef CONFIG_DEVFS_FS + cy_callout_driver.name = "cua/%d"; +#else cy_callout_driver.name = "cua"; +#endif cy_callout_driver.major = TTYAUX_MAJOR; cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT; diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/tty_io.c Wed Jul 24 14:03:38 2002 @@ -150,8 +150,7 @@ extern void tty3215_init(void); extern void tub3270_con_init(void); extern void tub3270_init(void); -extern void rs285_console_init(void); -extern void sa1100_rs_console_init(void); +extern void uart_console_init(void); extern void sgi_serial_console_init(void); extern void sci_console_init(void); extern void tx3912_console_init(void); @@ -456,11 +455,12 @@ } file_list_unlock(); - /* FIXME! What are the locking issues here? This may me overdoing things.. */ + /* FIXME! What are the locking issues here? This may me overdoing things.. + * this question is especially important now that we've removed the irqlock. */ { unsigned long flags; - save_flags(flags); cli(); + local_irq_save(flags); // FIXME: is this safe? if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (tty->driver.flush_buffer) @@ -468,7 +468,7 @@ if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); - restore_flags(flags); + local_irq_restore(flags); // FIXME: is this safe? } wake_up_interruptible(&tty->write_wait); @@ -1900,7 +1900,7 @@ fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE; tty->flip.buf_num = 0; - save_flags(flags); cli(); + local_irq_save(flags); // FIXME: is this safe? tty->flip.char_buf_ptr = tty->flip.char_buf; tty->flip.flag_buf_ptr = tty->flip.flag_buf; } else { @@ -1908,13 +1908,13 @@ fp = tty->flip.flag_buf; tty->flip.buf_num = 1; - save_flags(flags); cli(); + local_irq_save(flags); // FIXME: is this safe? tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE; tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE; } count = tty->flip.count; tty->flip.count = 0; - restore_flags(flags); + local_irq_restore(flags); // FIXME: is this safe? tty->ldisc.receive_buf(tty, cp, fp, count); } @@ -2220,17 +2220,11 @@ #ifdef CONFIG_STDIO_CONSOLE stdio_console_init(); #endif -#ifdef CONFIG_SERIAL_21285_CONSOLE - rs285_console_init(); -#endif -#ifdef CONFIG_SERIAL_SA1100_CONSOLE - sa1100_rs_console_init(); +#ifdef CONFIG_SERIAL_CORE_CONSOLE + uart_console_init(); #endif #ifdef CONFIG_ARC_CONSOLE arc_console_init(); -#endif -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - ambauart_console_init(); #endif #ifdef CONFIG_SERIAL_TX3912_CONSOLE tx3912_console_init(); diff -Nru a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c --- a/drivers/char/tty_ioctl.c Wed Jul 24 14:03:38 2002 +++ b/drivers/char/tty_ioctl.c Wed Jul 24 14:03:38 2002 @@ -97,7 +97,7 @@ int canon_change; struct termios old_termios = *tty->termios; - cli(); + local_irq_disable(); // FIXME: is this safe? *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; @@ -107,7 +107,7 @@ tty->canon_data = 0; tty->erasing = 0; } - sti(); + local_irq_enable(); // FIXME: is this safe? if (canon_change && !L_ICANON(tty) && tty->read_cnt) /* Get characters left over from canonical mode. */ wake_up_interruptible(&tty->read_wait); diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Wed Jul 24 14:03:35 2002 +++ b/drivers/char/vme_scc.c Wed Jul 24 14:03:35 2002 @@ -131,7 +131,11 @@ memset(&scc_driver, 0, sizeof(scc_driver)); scc_driver.magic = TTY_DRIVER_MAGIC; scc_driver.driver_name = "scc"; +#ifdef CONFIG_DEVFS_FS + scc_driver.name = "tts/%d"; +#else scc_driver.name = "ttyS"; +#endif scc_driver.major = TTY_MAJOR; scc_driver.minor_start = SCC_MINOR_BASE; scc_driver.num = 2; @@ -164,7 +168,11 @@ scc_driver.break_ctl = scc_break_ctl; scc_callout_driver = scc_driver; +#ifdef CONFIG_DEVFS_FS + scc_callout_driver.name = "cua/%d"; +#else scc_callout_driver.name = "cua"; +#endif scc_callout_driver.major = TTYAUX_MAJOR; scc_callout_driver.subtype = SERIAL_TYPE_CALLOUT; @@ -731,12 +739,10 @@ #ifdef CONFIG_MVME147_SCC if (MACH_IS_MVME147) brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; - else #endif #ifdef CONFIG_MVME162_SCC if (MACH_IS_MVME16x) brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2; - else #endif #ifdef CONFIG_BVME6000_SCC if (MACH_IS_BVME6000) @@ -783,6 +789,15 @@ } +/* Comment taken from sx.c (2.4.0): + I haven't the foggiest why the decrement use count has to happen + here. The whole linux serial drivers stuff needs to be redesigned. + My guess is that this is a hack to minimize the impact of a bug + elsewhere. Thinking about it some more. (try it sometime) Try + running minicom on a serial port that is driven by a modularized + driver. Have the modem hangup. Then remove the driver module. Then + exit minicom. I expect an "oops". -- REW */ + static void scc_hungup(void *ptr) { scc_disable_tx_interrupts(ptr); @@ -795,6 +810,7 @@ { scc_disable_tx_interrupts(ptr); scc_disable_rx_interrupts(ptr); + MOD_DEC_USE_COUNT; } @@ -809,6 +825,7 @@ SCC_ACCESS_INIT(port); save_flags(flags); + cli(); t = SCCread(TX_CTRL_REG); if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR); if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS); @@ -933,7 +950,7 @@ if (port->gs.count == 1) { MOD_INC_USE_COUNT; } - retval = block_til_ready(port, filp); + retval = gs_block_til_ready(port, filp); if (retval) { MOD_DEC_USE_COUNT; diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Wed Jul 24 14:03:39 2002 +++ b/drivers/char/vt.c Wed Jul 24 14:03:39 2002 @@ -33,10 +33,6 @@ #include #include -#ifdef CONFIG_FB_COMPAT_XPMAC -#include -#endif /* CONFIG_FB_COMPAT_XPMAC */ - char vt_dont_switch; extern struct tty_driver console_driver; @@ -113,8 +109,7 @@ if (hz > 20 && hz < 32767) count = 1193180 / hz; - save_flags(flags); - cli(); + local_irq_save(flags); // FIXME: is this safe? del_timer(&sound_timer); if (count) { /* enable counter 2 */ @@ -131,7 +126,7 @@ } } else kd_nosound(0); - restore_flags(flags); + local_irq_restore(flags); return; } @@ -1047,68 +1042,6 @@ return -EPERM; vt_dont_switch = 0; return 0; -#ifdef CONFIG_FB_COMPAT_XPMAC - case VC_GETMODE: - { - struct vc_mode mode; - - i = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct vc_mode)); - if (i == 0) - i = console_getmode(&mode); - if (i) - return i; - if (copy_to_user((void *) arg, &mode, sizeof(mode))) - return -EFAULT; - return 0; - } - case VC_SETMODE: - case VC_INQMODE: - { - struct vc_mode mode; - - if (!perm) - return -EPERM; - if (copy_from_user(&mode, (void *) arg, sizeof(mode))) - return -EFAULT; - return console_setmode(&mode, cmd == VC_SETMODE); - } - case VC_SETCMAP: - { - unsigned char cmap[3][256], *p; - int n_entries, cmap_size, i, j; - - if (!perm) - return -EPERM; - if (arg == (unsigned long) VC_POWERMODE_INQUIRY - || arg <= VESA_POWERDOWN) { - /* compatibility hack: VC_POWERMODE - was changed from 0x766a to 0x766c */ - return console_powermode((int) arg); - } - if (get_user(cmap_size, (int *) arg)) - return -EFAULT; - if (cmap_size % 3) - return -EINVAL; - n_entries = cmap_size / 3; - if ((unsigned) n_entries > 256) - return -EINVAL; - p = (unsigned char *) (arg + sizeof(int)); - for (j = 0; j < n_entries; ++j) - for (i = 0; i < 3; ++i) - if (get_user(cmap[i][j], p++)) - return -EFAULT; - return console_setcmap(n_entries, cmap[0], - cmap[1], cmap[2]); - } - case VC_GETCMAP: - /* not implemented yet */ - return -ENOIOCTLCMD; - case VC_POWERMODE: - if (!perm) - return -EPERM; - return console_powermode((int) arg); -#endif /* CONFIG_FB_COMPAT_XPMAC */ default: return -ENOIOCTLCMD; } diff -Nru a/drivers/dio/dio.c b/drivers/dio/dio.c --- a/drivers/dio/dio.c Wed Jul 24 14:03:39 2002 +++ b/drivers/dio/dio.c Wed Jul 24 14:03:39 2002 @@ -115,8 +115,14 @@ static int __init dio_find_slow(int deviceid) { /* Called to find a DIO device before the full bus scan has run. Basically - only used by the console driver. */ + * only used by the console driver. + * We don't do the primary+secondary ID encoding thing here. Maybe we should. + * (that would break the topcat detection, though. I need to think about + * the whole primary/secondary ID thing.) + */ int scode; + u_char prid; + for (scode = 0; scode < DIO_SCMAX; scode++) { void *va; @@ -128,12 +134,23 @@ if (!va || !hwreg_present(va + DIO_IDOFF)) continue; /* no board present at that select code */ - if (DIO_ID(va) == deviceid) + /* We aren't very likely to want to use this to get at the IHPIB, + * but maybe it's returning the same ID as the card we do want... + */ + if (!DIO_ISIHPIB(scode)) + prid = DIO_ID(va); + else + prid = DIO_ID_IHPIB; + + if (prid == deviceid) return scode; } return 0; } +/* Aargh: we use 0 for an error return code, but select code 0 exists! + * FIXME (trivial, use -1, but requires changes to all the drivers :-< ) + */ int dio_find(int deviceid) { if (blist) @@ -151,7 +168,7 @@ /* This is the function that scans the DIO space and works out what * hardware is actually present. */ -void __init dio_init(void) +static int __init dio_init(void) { int scode; struct dioboard *b, *bprev = NULL; @@ -193,10 +210,10 @@ b->scode = scode; b->ipl = DIO_IPL(va); b->name = dio_getname(b->id); - printk("select code %3d: ID %02X", scode, prid); + printk("select code %3d: ipl %d: ID %02X", scode, b->ipl, prid); if (DIO_NEEDSSECID(b->id)) printk(":%02X", secid); - printk(" %s\n", b->name); + printk(": %s\n", b->name); b->next = NULL; @@ -206,6 +223,7 @@ blist = b; bprev = b; } + return 0; } subsys_initcall(dio_init); @@ -224,9 +242,9 @@ return 0; else if (DIO_SCINHOLE(scode)) return 0; - else if (scode == DIO_IHPIBSCODE) /* this should really be #ifdef CONFIG_IHPIB */ - return (void*)DIO_IHPIBADDR; /* or something similar... */ - + else if (DIO_ISIHPIB(scode)) + return (void*)DIO_IHPIBADDR; + return (void*)(DIO_VIRADDRBASE + DIO_BASE + scode * 0x10000); } diff -Nru a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c --- a/drivers/hotplug/cpqphp_core.c Wed Jul 24 14:03:35 2002 +++ b/drivers/hotplug/cpqphp_core.c Wed Jul 24 14:03:35 2002 @@ -81,15 +81,15 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = { - owner: THIS_MODULE, - set_attention_status: set_attention_status, - enable_slot: process_SI, - disable_slot: process_SS, - 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, + .owner = THIS_MODULE, + .set_attention_status = set_attention_status, + .enable_slot = process_SI, + .disable_slot = process_SS, + .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, }; @@ -1387,14 +1387,14 @@ static struct pci_device_id hpcd_pci_tbl[] __devinitdata = { { /* handle any PCI Hotplug controller */ - class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), - class_mask: ~0, + .class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), + .class_mask = ~0, /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { /* end: all zeroes */ } }; @@ -1404,9 +1404,9 @@ static struct pci_driver cpqhpc_driver = { - name: "pci_hotplug", - id_table: hpcd_pci_tbl, - probe: cpqhpc_probe, + .name = "pci_hotplug", + .id_table = hpcd_pci_tbl, + .probe = cpqhpc_probe, /* remove: cpqhpc_remove_one, */ }; diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c --- a/drivers/hotplug/cpqphp_pci.c Wed Jul 24 14:03:39 2002 +++ b/drivers/hotplug/cpqphp_pci.c Wed Jul 24 14:03:39 2002 @@ -232,17 +232,17 @@ static struct pci_visit configure_functions = { - visit_pci_dev: configure_visit_pci_dev, + .visit_pci_dev = configure_visit_pci_dev, }; static struct pci_visit unconfigure_functions_phase1 = { - post_visit_pci_dev: unconfigure_visit_pci_dev_phase1 + .post_visit_pci_dev = unconfigure_visit_pci_dev_phase1 }; static struct pci_visit unconfigure_functions_phase2 = { - post_visit_pci_bus: unconfigure_visit_pci_bus_phase2, - post_visit_pci_dev: unconfigure_visit_pci_dev_phase2 + .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2, + .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2 }; diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Wed Jul 24 14:03:38 2002 +++ b/drivers/hotplug/ibmphp_core.c Wed Jul 24 14:03:38 2002 @@ -893,12 +893,12 @@ } static struct pci_visit ibm_unconfigure_functions_phase1 = { - post_visit_pci_dev: ibm_unconfigure_visit_pci_dev_phase1, + .post_visit_pci_dev = ibm_unconfigure_visit_pci_dev_phase1, }; static struct pci_visit ibm_unconfigure_functions_phase2 = { - post_visit_pci_bus: ibm_unconfigure_visit_pci_bus_phase2, - post_visit_pci_dev: ibm_unconfigure_visit_pci_dev_phase2, + .post_visit_pci_bus = ibm_unconfigure_visit_pci_bus_phase2, + .post_visit_pci_dev = ibm_unconfigure_visit_pci_dev_phase2, }; static int ibm_unconfigure_device (struct pci_func *func) @@ -962,7 +962,7 @@ } static struct pci_visit configure_functions = { - visit_pci_dev: configure_visit_pci_dev, + .visit_pci_dev =configure_visit_pci_dev, }; static int ibm_configure_device (struct pci_func *func) @@ -1494,19 +1494,19 @@ } struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { - owner: THIS_MODULE, - set_attention_status: set_attention_status, - enable_slot: enable_slot, - disable_slot: ibmphp_disable_slot, - hardware_test: NULL, - get_power_status: get_power_status, - get_attention_status: get_attention_status, - get_latch_status: get_latch_status, - get_adapter_status: get_adapter_present, + .owner = THIS_MODULE, + .set_attention_status = set_attention_status, + .enable_slot = enable_slot, + .disable_slot = ibmphp_disable_slot, + .hardware_test = NULL, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_present, /* get_max_bus_speed_status: get_max_bus_speed, - get_max_adapter_speed_status: get_max_adapter_speed, - get_cur_bus_speed_status: get_cur_bus_speed, - get_card_bus_names_status: get_card_bus_names, + .get_max_adapter_speed_status = get_max_adapter_speed, + .get_cur_bus_speed_status = get_cur_bus_speed, + .get_card_bus_names_status = get_card_bus_names, */ }; diff -Nru a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c --- a/drivers/hotplug/pci_hotplug_core.c Wed Jul 24 14:03:37 2002 +++ b/drivers/hotplug/pci_hotplug_core.c Wed Jul 24 14:03:37 2002 @@ -48,7 +48,7 @@ #define MY_NAME THIS_MODULE->name #endif -#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __FUNCTION__, ## arg); } while (0) +#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## 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) @@ -109,6 +109,9 @@ case S_IFDIR: inode->i_op = &pcihpfs_dir_inode_operations; inode->i_fop = &simple_dir_operations; + + /* directory inodes start off with i_nlink == 2 (for "." entry) */ + inode->i_nlink++; break; } } @@ -227,71 +230,71 @@ } static struct file_operations default_file_operations = { - read: default_read_file, - write: default_write_file, - open: default_open, - llseek: default_file_lseek, + .read = default_read_file, + .write = default_write_file, + .open = default_open, + .llseek = default_file_lseek, }; /* file ops for the "power" files */ static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset); static ssize_t power_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos); static struct file_operations power_file_operations = { - read: power_read_file, - write: power_write_file, - open: default_open, - llseek: default_file_lseek, + .read = power_read_file, + .write = power_write_file, + .open = default_open, + .llseek = default_file_lseek, }; /* file ops for the "attention" files */ static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset); static ssize_t attention_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos); static struct file_operations attention_file_operations = { - read: attention_read_file, - write: attention_write_file, - open: default_open, - llseek: default_file_lseek, + .read = attention_read_file, + .write = attention_write_file, + .open = default_open, + .llseek = default_file_lseek, }; /* file ops for the "latch" files */ static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset); static struct file_operations latch_file_operations = { - read: latch_read_file, - write: default_write_file, - open: default_open, - llseek: default_file_lseek, + .read = latch_read_file, + .write = default_write_file, + .open = default_open, + .llseek = default_file_lseek, }; /* file ops for the "presence" files */ static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset); static struct file_operations presence_file_operations = { - read: presence_read_file, - write: default_write_file, - open: default_open, - llseek: default_file_lseek, + .read = presence_read_file, + .write = default_write_file, + .open = default_open, + .llseek = default_file_lseek, }; /* file ops for the "test" files */ static ssize_t test_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos); static struct file_operations test_file_operations = { - read: default_read_file, - write: test_write_file, - open: default_open, - llseek: default_file_lseek, + .read = default_read_file, + .write = test_write_file, + .open = default_open, + .llseek = default_file_lseek, }; static struct inode_operations pcihpfs_dir_inode_operations = { - create: pcihpfs_create, - lookup: simple_lookup, - unlink: pcihpfs_unlink, - mkdir: pcihpfs_mkdir, - rmdir: pcihpfs_rmdir, - mknod: pcihpfs_mknod, + .create = pcihpfs_create, + .lookup = simple_lookup, + .unlink = pcihpfs_unlink, + .mkdir = pcihpfs_mkdir, + .rmdir = pcihpfs_rmdir, + .mknod = pcihpfs_mknod, }; static struct super_operations pcihpfs_ops = { - statfs: simple_statfs, - drop_inode: generic_delete_inode, + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, }; static int pcihpfs_fill_super(struct super_block *sb, void *data, int silent) @@ -327,10 +330,10 @@ } static struct file_system_type pcihpfs_type = { - owner: THIS_MODULE, - name: "pcihpfs", - get_sb: pcihpfs_get_sb, - kill_sb: kill_litter_super, + .owner = THIS_MODULE, + .name = "pcihpfs", + .get_sb = pcihpfs_get_sb, + .kill_sb = kill_litter_super, }; static int get_mount (void) diff -Nru a/drivers/hotplug/pci_hotplug_util.c b/drivers/hotplug/pci_hotplug_util.c --- a/drivers/hotplug/pci_hotplug_util.c Wed Jul 24 14:03:38 2002 +++ b/drivers/hotplug/pci_hotplug_util.c Wed Jul 24 14:03:38 2002 @@ -41,7 +41,7 @@ #define MY_NAME THIS_MODULE->name #endif -#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt, MY_NAME, __FUNCTION__, ## arg); } while (0) +#define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## 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) diff -Nru a/drivers/hotplug/pcihp_skeleton.c b/drivers/hotplug/pcihp_skeleton.c --- a/drivers/hotplug/pcihp_skeleton.c Wed Jul 24 14:03:38 2002 +++ b/drivers/hotplug/pcihp_skeleton.c Wed Jul 24 14:03:38 2002 @@ -89,15 +89,15 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *value); static struct hotplug_slot_ops skel_hotplug_slot_ops = { - owner: THIS_MODULE, - enable_slot: enable_slot, - disable_slot: disable_slot, - set_attention_status: set_attention_status, - 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, + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .set_attention_status = set_attention_status, + .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, }; diff -Nru a/drivers/ide/device.c b/drivers/ide/device.c --- a/drivers/ide/device.c Wed Jul 24 14:03:37 2002 +++ b/drivers/ide/device.c Wed Jul 24 14:03:37 2002 @@ -150,16 +150,16 @@ if (!ata_status(drive, 0, BUSY_STAT)) { unsigned long flags; - __save_flags(flags); + local_save_flags(flags); local_irq_enable(); timeout += jiffies; while (!ata_status(drive, 0, BUSY_STAT)) { if (time_after(jiffies, timeout)) { - __restore_flags(flags); + local_irq_restore(flags); return ata_error(drive, rq, "status timeout"); } } - __restore_flags(flags); + local_irq_restore(flags); } /* diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c --- a/drivers/ide/hd.c Wed Jul 24 14:03:36 2002 +++ b/drivers/ide/hd.c Wed Jul 24 14:03:36 2002 @@ -83,9 +83,6 @@ static char recalibrate[MAX_HD]; static char special_op[MAX_HD]; -static int access_count[MAX_HD]; -static char busy[MAX_HD]; -static DECLARE_WAIT_QUEUE_HEAD(busy_wait); static int reset; static int hd_error; @@ -644,7 +641,7 @@ g.heads = hd_info[dev].head; g.sectors = hd_info[dev].sect; g.cylinders = hd_info[dev].cyl; - g.start = get_start_sect(inode->i_rdev); + g.start = get_start_sect(inode->i_bdev); return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; } @@ -653,14 +650,6 @@ return -EACCES; return revalidate_hddisk(inode->i_rdev, 1); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; } @@ -668,14 +657,9 @@ static int hd_open(struct inode * inode, struct file * filp) { - int target; - target = DEVICE_NR(inode->i_rdev); - + int target = DEVICE_NR(inode->i_rdev); if (target >= NR_HD) return -ENODEV; - while (busy[target]) - sleep_on(&busy_wait); - access_count[target]++; return 0; } @@ -683,12 +667,6 @@ * Releasing a block device means we sync() it, so that it can safely * be forgotten about... */ -static int hd_release(struct inode * inode, struct file * file) -{ - int target = DEVICE_NR(inode->i_rdev); - access_count[target]--; - return 0; -} extern struct block_device_operations hd_fops; @@ -715,7 +693,6 @@ static struct block_device_operations hd_fops = { .open = hd_open, - .release = hd_release, .ioctl = hd_ioctl, }; @@ -854,13 +831,9 @@ return 0; } -#define DEVICE_BUSY busy[target] -#define USAGE access_count[target] #define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl) /* We assume that the BIOS parameters do not change, so the disk capacity will not change */ -#undef MAYBE_REINIT -#define GENDISK_STRUCT hd_gendisk /* * This routine is called to flush all partitions and partition tables @@ -872,36 +845,15 @@ */ static int revalidate_hddisk(kdev_t dev, int maxusage) { - int target; - struct gendisk * gdev; - int res; - long flags; - - target = DEVICE_NR(dev); - gdev = &GENDISK_STRUCT; - - save_flags(flags); - cli(); - if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); - return -EBUSY; - } - DEVICE_BUSY = 1; - restore_flags(flags); - - res = wipe_partitions(dev); - if (res) - goto leave; - -#ifdef MAYBE_REINIT - MAYBE_REINIT; -#endif - - grok_partitions(dev, CAPACITY); - -leave: - DEVICE_BUSY = 0; - wake_up(&busy_wait); + int target = DEVICE_NR(dev); + kdev_t device = mk_kdev(MAJOR_NR, target << 6); + int res = dev_lock_part(device); + if (res < 0) + return res; + res = wipe_partitions(device); + if (!res) + grok_partitions(device, CAPACITY); + dev_unlock_part(device); return res; } diff -Nru a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c --- a/drivers/ide/hptraid.c Wed Jul 24 14:03:39 2002 +++ b/drivers/ide/hptraid.c Wed Jul 24 14:03:39 2002 @@ -122,11 +122,6 @@ return 0; } - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; }; diff -Nru a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c --- a/drivers/ide/ide-pmac.c Wed Jul 24 14:03:39 2002 +++ b/drivers/ide/ide-pmac.c Wed Jul 24 14:03:39 2002 @@ -419,10 +419,10 @@ OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); udelay(1); - __save_flags(flags); + local_save_flags(flags); local_irq_enable(); result = wait_for_ready(drive); - __restore_flags(flags); + local_irq_restore(flags); ata_irq_enable(drive, 1); if (result) printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Wed Jul 24 14:03:38 2002 +++ b/drivers/ide/ide-taskfile.c Wed Jul 24 14:03:38 2002 @@ -194,22 +194,16 @@ request_queue_t *q = &drive->queue; struct list_head *queue_head = &q->queue_head; DECLARE_COMPLETION(wait); + struct request req; #ifdef CONFIG_BLK_DEV_PDC4030 if (ch->chipset == ide_pdc4030 && buf) return -ENOSYS; /* special drive cmds not supported */ #endif - rq = __blk_get_request(&drive->queue, READ); - if (!rq) - rq = __blk_get_request(&drive->queue, WRITE); - - /* - * FIXME: Make sure there is a free slot on the list! - */ - - BUG_ON(!rq); - + memset(&req, 0, sizeof(req)); + rq = &req; + rq->flags = REQ_SPECIAL; rq->buffer = buf; rq->special = ar; diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Wed Jul 24 14:03:39 2002 +++ b/drivers/ide/ide.c Wed Jul 24 14:03:39 2002 @@ -288,7 +288,7 @@ u8 err = 0; /* FIXME: --bzolnier */ - __save_flags(flags); + local_save_flags(flags); local_irq_enable(); printk("%s: %s: status=0x%02x", drive->name, msg, drive->status); @@ -337,7 +337,7 @@ #endif printk("\n"); } - __restore_flags (flags); + local_irq_restore (flags); return err; } @@ -1104,9 +1104,6 @@ if (drive->driver == NULL) ide_driver_module(); - - while (drive->busy) - sleep_on(&drive->wqueue); ++drive->usage; if (ata_ops(drive) && ata_ops(drive)->open) diff -Nru a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c --- a/drivers/ide/ioctl.c Wed Jul 24 14:03:37 2002 +++ b/drivers/ide/ioctl.c Wed Jul 24 14:03:37 2002 @@ -343,19 +343,6 @@ case BLKRRPART: /* Re-read partition tables */ return ata_revalidate(inode->i_rdev); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - case BLKELVGET: - case BLKELVSET: - case BLKBSZGET: - case BLKBSZSET: - return blk_ioctl(inode->i_bdev, cmd, arg); - /* Now check whatever this particular ioctl has a device type * specific implementation. */ diff -Nru a/drivers/ide/main.c b/drivers/ide/main.c --- a/drivers/ide/main.c Wed Jul 24 14:03:35 2002 +++ b/drivers/ide/main.c Wed Jul 24 14:03:35 2002 @@ -249,28 +249,22 @@ */ int ata_revalidate(kdev_t i_rdev) { + kdev_t device = mk_kdev(major(i_rdev), minor(i_rdev) & ~PARTN_MASK); struct ata_device *drive; - unsigned long flags; int res; - if ((drive = get_info_ptr(i_rdev)) == NULL) + if ((drive = get_info_ptr(device)) == NULL) return -ENODEV; - /* FIXME: The locking here doesn't make the slightest sense! */ - spin_lock_irqsave(&ide_lock, flags); - - if (drive->busy || (drive->usage > 1)) { - spin_unlock_irqrestore(&ide_lock, flags); - - return -EBUSY; - } - - drive->busy = 1; MOD_INC_USE_COUNT; - spin_unlock_irqrestore(&ide_lock, flags); + res = dev_lock_part(device); + if (res < 0) { + MOD_DEC_USE_COUNT; + return res; + } - res = wipe_partitions(i_rdev); + res = wipe_partitions(device); if (!res) { if (ata_ops(drive) && ata_ops(drive)->revalidate) { ata_get(ata_ops(drive)); @@ -281,14 +275,11 @@ ata_ops(drive)->revalidate(drive); ata_put(ata_ops(drive)); } else - grok_partitions(i_rdev, ata_capacity(drive)); + grok_partitions(device, ata_capacity(drive)); } - drive->busy = 0; - wake_up(&drive->wqueue); - + dev_unlock_part(device); MOD_DEC_USE_COUNT; - return res; } @@ -1089,29 +1080,18 @@ */ int ide_unregister_subdriver(struct ata_device *drive) { - unsigned long flags; - - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - #if 0 - if (__MOD_IN_USE(ata_ops(drive)->owner)) { - restore_flags(flags); + if (__MOD_IN_USE(ata_ops(drive)->owner)) return 1; - } #endif - if (drive->usage || drive->busy || !ata_ops(drive)) { - restore_flags(flags); /* all CPUs */ + if (drive->usage || drive->busy || !ata_ops(drive)) return 1; - } #if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) pnpide_init(0); #endif drive->driver = NULL; - - restore_flags(flags); /* all CPUs */ return 0; } diff -Nru a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c --- a/drivers/ide/pdcraid.c Wed Jul 24 14:03:38 2002 +++ b/drivers/ide/pdcraid.c Wed Jul 24 14:03:38 2002 @@ -152,11 +152,6 @@ return 0; } - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: printk("Invalid ioctl \n"); return -EINVAL; diff -Nru a/drivers/ide/probe.c b/drivers/ide/probe.c --- a/drivers/ide/probe.c Wed Jul 24 14:03:35 2002 +++ b/drivers/ide/probe.c Wed Jul 24 14:03:35 2002 @@ -733,7 +733,7 @@ ch->straight8 = 0; - __save_flags(flags); + local_save_flags(flags); local_irq_enable(); /* needed for jiffies and irq probing */ /* @@ -852,7 +852,7 @@ if (ch->reset) ata_reset(ch); - __restore_flags(flags); + local_irq_restore(flags); /* * Now setup the PIO transfer modes of the drives on this channel. @@ -869,7 +869,7 @@ return; not_found: - __restore_flags(flags); + local_irq_restore(flags); } /* diff -Nru a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c --- a/drivers/ide/q40ide.c Wed Jul 24 14:03:38 2002 +++ b/drivers/ide/q40ide.c Wed Jul 24 14:03:38 2002 @@ -79,8 +79,8 @@ for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { hw_regs_t hw; - ide_setup_ports(&hw,(ide_ioreg_t) pcide_bases[i], (int *)pcide_offsets, - pcide_bases[i] + 0x206, + ide_setup_ports(&hw, (ide_ioreg_t)pcide_bases[i], (int *)pcide_offsets, + (ide_ioreg_t)pcide_bases[i]+0x206, 0, NULL, q40ide_default_irq(pcide_bases[i])); ide_register_hw(&hw); } diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Wed Jul 24 14:03:36 2002 +++ b/drivers/ieee1394/sbp2.c Wed Jul 24 14:03:36 2002 @@ -3097,7 +3097,7 @@ /* * Called by scsi stack to get bios parameters (used by fdisk, and at boot). */ -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]) +static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]) { int heads, sectors, cylinders; diff -Nru a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h --- a/drivers/ieee1394/sbp2.h Wed Jul 24 14:03:36 2002 +++ b/drivers/ieee1394/sbp2.h Wed Jul 24 14:03:36 2002 @@ -542,7 +542,7 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt); static const char *sbp2scsi_info (struct Scsi_Host *host); void sbp2scsi_setup(char *str, int *ints); -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); +static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]); static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c --- a/drivers/input/joystick/a3d.c Wed Jul 24 14:03:35 2002 +++ b/drivers/input/joystick/a3d.c Wed Jul 24 14:03:35 2002 @@ -84,8 +84,7 @@ t = gameport_time(gameport, A3D_MAX_START); s = gameport_time(gameport, A3D_MAX_STROBE); - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); v = gameport_read(gameport); @@ -98,7 +97,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return i; } diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c --- a/drivers/input/joystick/adi.c Wed Jul 24 14:03:37 2002 +++ b/drivers/input/joystick/adi.c Wed Jul 24 14:03:37 2002 @@ -152,8 +152,7 @@ s[i] = 0; } - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); v = z = gameport_read(gameport); @@ -172,7 +171,7 @@ } } while (t[0] > 0 || t[1] > 0); - __restore_flags(flags); + local_irq_restore(flags); return; } diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c --- a/drivers/input/joystick/analog.c Wed Jul 24 14:03:37 2002 +++ b/drivers/input/joystick/analog.c Wed Jul 24 14:03:37 2002 @@ -232,11 +232,10 @@ loopout = (ANALOG_LOOP_TIME * port->loop) / 1000; timeout = ANALOG_MAX_TIME * port->speed; - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); GET_TIME(now); - __restore_flags(flags); + local_irq_restore(flags); start = now; this = port->mask; @@ -246,10 +245,10 @@ loop = now; last = this; - __cli(); + local_irq_disable(); this = gameport_read(gameport) & port->mask; GET_TIME(now); - __restore_flags(flags); + local_irq_restore(flags); if ((last ^ this) && (DELTA(loop, now) < loopout)) { data[i] = last ^ this; diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c --- a/drivers/input/joystick/cobra.c Wed Jul 24 14:03:38 2002 +++ b/drivers/input/joystick/cobra.c Wed Jul 24 14:03:38 2002 @@ -73,8 +73,7 @@ t[i] = COBRA_MAX_STROBE; } - __save_flags(flags); - __cli(); + local_irq_save(flags); u = gameport_read(gameport); @@ -91,7 +90,7 @@ } } while (t[0] > 0 || t[1] > 0); - __restore_flags(flags); + local_irq_restore(flags); ret = 0; diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c --- a/drivers/input/joystick/gamecon.c Wed Jul 24 14:03:39 2002 +++ b/drivers/input/joystick/gamecon.c Wed Jul 24 14:03:39 2002 @@ -113,13 +113,12 @@ * Request the pad to transmit data */ - __save_flags(flags); - __cli(); + local_irq_save(flags); for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) { parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0)); udelay(GC_N64_DWS); } - __restore_flags(flags); + local_irq_restore(flags); /* * Wait for the pad response to be loaded into the 33-bit register of the adapter @@ -270,8 +269,7 @@ parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */ udelay(GC_PSX_DELAY * 2); - __save_flags(flags); - __cli(); + local_irq_save(flags); gc_psx_command(gc, 0x01); /* Access pad */ id = gc_psx_command(gc, 0x42); /* Get device id */ @@ -280,7 +278,7 @@ data[i] = gc_psx_command(gc, 0); } else id = 0; - __restore_flags(flags); + local_irq_restore(flags); parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c --- a/drivers/input/joystick/gf2k.c Wed Jul 24 14:03:36 2002 +++ b/drivers/input/joystick/gf2k.c Wed Jul 24 14:03:36 2002 @@ -106,8 +106,7 @@ i = 0; - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); v = gameport_read(gameport);; @@ -121,7 +120,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return i; } @@ -137,8 +136,7 @@ unsigned long flags; int i, t; - __save_flags(flags); - __cli(); + local_irq_save(flags); i = 0; do { @@ -150,7 +148,7 @@ gameport_trigger(gameport); - __restore_flags(flags); + local_irq_restore(flags); } /* diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c --- a/drivers/input/joystick/grip.c Wed Jul 24 14:03:37 2002 +++ b/drivers/input/joystick/grip.c Wed Jul 24 14:03:37 2002 @@ -98,8 +98,7 @@ t = strobe; i = 0; - __save_flags(flags); - __cli(); + local_irq_save(flags); v = gameport_read(gameport) >> shift; @@ -112,7 +111,7 @@ } } while (i < GRIP_LENGTH_GPP && t > 0); - __restore_flags(flags); + local_irq_restore(flags); if (i < GRIP_LENGTH_GPP) return -1; @@ -140,8 +139,7 @@ status = buf = i = j = 0; t = strobe; - __save_flags(flags); - __cli(); + local_irq_save(flags); v = w = (gameport_read(gameport) >> shift) & 3; @@ -176,7 +174,7 @@ } while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0); - __restore_flags(flags); + local_irq_restore(flags); return -(status != 0xf); } diff -Nru a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c --- a/drivers/input/joystick/guillemot.c Wed Jul 24 14:03:37 2002 +++ b/drivers/input/joystick/guillemot.c Wed Jul 24 14:03:37 2002 @@ -98,8 +98,7 @@ t = gameport_time(gameport, GUILLEMOT_MAX_START); s = gameport_time(gameport, GUILLEMOT_MAX_STROBE); - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); v = gameport_read(gameport); @@ -113,7 +112,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return i; } diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c --- a/drivers/input/joystick/interact.c Wed Jul 24 14:03:35 2002 +++ b/drivers/input/joystick/interact.c Wed Jul 24 14:03:35 2002 @@ -103,8 +103,7 @@ t = gameport_time(gameport, INTERACT_MAX_START); s = gameport_time(gameport, INTERACT_MAX_STROBE); - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); v = gameport_read(gameport); @@ -120,7 +119,7 @@ } } - __restore_flags(flags); + local_irq_restore(flags); return i; } diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c --- a/drivers/input/joystick/sidewinder.c Wed Jul 24 14:03:39 2002 +++ b/drivers/input/joystick/sidewinder.c Wed Jul 24 14:03:39 2002 @@ -149,8 +149,7 @@ pending = 0; sched = 0; - __save_flags(flags); /* Quiet, please */ - __cli(); + local_irq_save(flags); /* Quiet, please */ gameport_trigger(gameport); /* Trigger */ v = gameport_read(gameport); @@ -193,7 +192,7 @@ } } - __restore_flags(flags); /* Done - relax */ + local_irq_restore(flags); /* Done - relax */ #ifdef SW_DEBUG { @@ -245,8 +244,7 @@ unsigned long flags; int i, t; - __save_flags(flags); - __cli(); + local_irq_save(flags); i = 0; do { @@ -258,7 +256,7 @@ gameport_trigger(gameport); /* Last trigger */ - __restore_flags(flags); + local_irq_restore(flags); } /* diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c --- a/drivers/input/joystick/tmdc.c Wed Jul 24 14:03:37 2002 +++ b/drivers/input/joystick/tmdc.c Wed Jul 24 14:03:37 2002 @@ -125,8 +125,7 @@ i[k] = j[k] = 0; } - __save_flags(flags); - __cli(); + local_irq_save(flags); gameport_trigger(gameport); w = gameport_read(gameport) >> 4; @@ -153,7 +152,7 @@ } } while (t[0] > 0 || t[1] > 0); - __restore_flags(flags); + local_irq_restore(flags); return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1); } diff -Nru a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile --- a/drivers/macintosh/Makefile Wed Jul 24 14:03:37 2002 +++ b/drivers/macintosh/Makefile Wed Jul 24 14:03:37 2002 @@ -17,7 +17,9 @@ obj-$(CONFIG_PMAC_PBOOK) += mediabay.o obj-$(CONFIG_MAC_SERIAL) += macserial.o -obj-$(CONFIG_NVRAM) += nvram.o +ifneq ($(CONFIG_MAC),y) + obj-$(CONFIG_NVRAM) += nvram.o +endif obj-$(CONFIG_MAC_HID) += mac_hid.o obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_PPC_RTC) += rtc.o diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c --- a/drivers/macintosh/adb.c Wed Jul 24 14:03:38 2002 +++ b/drivers/macintosh/adb.c Wed Jul 24 14:03:38 2002 @@ -35,6 +35,7 @@ #include #include #include +#include #include #ifdef CONFIG_PPC #include @@ -64,7 +65,7 @@ #ifdef CONFIG_ADB_IOP &adb_iop_driver, #endif -#ifdef CONFIG_ADB_PMU +#if defined(CONFIG_ADB_PMU) || defined(CONFIG_ADB_PMU68K) &via_pmu_driver, #endif #ifdef CONFIG_ADB_MACIO @@ -311,9 +312,11 @@ #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&adb_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ +#ifdef CONFIG_PPC if (machine_is_compatible("AAPL,PowerBook1998") || machine_is_compatible("PowerBook1,1")) sleepy_trackpad = 1; +#endif /* CONFIG_PPC */ init_completion(&adb_probe_task_comp); adbdev_init(); adb_reset_bus(); diff -Nru a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c --- a/drivers/macintosh/adbhid.c Wed Jul 24 14:03:38 2002 +++ b/drivers/macintosh/adbhid.c Wed Jul 24 14:03:38 2002 @@ -944,8 +944,10 @@ static int __init adbhid_init(void) { +#ifndef CONFIG_MAC if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) return 0; +#endif led_request.complete = 1; diff -Nru a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c --- a/drivers/macintosh/via-cuda.c Wed Jul 24 14:03:36 2002 +++ b/drivers/macintosh/via-cuda.c Wed Jul 24 14:03:36 2002 @@ -191,7 +191,9 @@ if (via == NULL) return -ENODEV; +#ifdef CONFIG_PPC request_OF_resource(vias, 0, NULL); +#endif if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); @@ -224,12 +226,19 @@ static int __init cuda_init(void) { +#ifdef CONFIG_PPC if (via == NULL) return -ENODEV; -#ifndef CONFIG_PPC + return 0; +#else + int err = cuda_init_via(); + if (err) { + printk(KERN_ERR "cuda_init_via() failed\n"); + return -ENODEV; + } + return via_cuda_start(); #endif - return 0; } #endif /* CONFIG_ADB */ diff -Nru a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c --- a/drivers/macintosh/via-macii.c Wed Jul 24 14:03:36 2002 +++ b/drivers/macintosh/via-macii.c Wed Jul 24 14:03:36 2002 @@ -10,6 +10,8 @@ * Rewrite for Unified ADB by Joshua M. Thompson (funaho@jurai.org) * * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. + * 2000-03-29 Tony Mantler + * - Big overhaul, should actually work now. */ #include @@ -98,7 +100,6 @@ static enum macii_state { idle, - sent_first_byte, sending, reading, read_done, @@ -133,7 +134,7 @@ via = via1; - printk("adb: Mac II ADB Driver v0.4 for Unified ADB\n"); + printk("adb: Mac II ADB Driver v1.0 for Unified ADB\n"); return 0; } @@ -186,7 +187,7 @@ static int in_poll=0; static struct adb_request req; unsigned long flags; - + if (in_poll) printk("macii_queue_poll: double poll!\n"); in_poll++; @@ -212,7 +213,7 @@ static int in_retransmit = 0; static struct adb_request rt; unsigned long flags; - + if (in_retransmit) printk("macii_retransmit: double retransmit!\n"); in_retransmit++; @@ -256,11 +257,11 @@ { unsigned long flags; - if (req->nbytes < 2 || req->data[0] != ADB_PACKET) { + if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { req->complete = 1; return -EINVAL; } - + req->next = 0; req->sent = 0; req->complete = 0; @@ -319,7 +320,7 @@ req = current_req; if (!req) return; - + /* assert macii_state == idle */ if (macii_state != idle) { printk("macii_start: called while driver busy (%p %x %x)!\n", @@ -333,7 +334,9 @@ * IRQ signaled ?? (means ADB controller wants to send, or might * be end of packet if we were reading) */ +#if 0 /* FIXME: This is broke broke broke, for some reason */ if ((via[B] & TREQ) == 0) { + printk("macii_start: weird poll stuff. huh?\n"); /* * FIXME - we need to restart this on a timer * or a collision at boot hangs us. @@ -359,6 +362,7 @@ need_poll = 0; } } +#endif /* * Another retry pending? (sanity check) */ @@ -368,7 +372,7 @@ /* Now send it. Be careful though, that first byte of the request */ /* is actually ADB_PACKET; the real data begins at index 1! */ - + /* store command byte */ command_byte = req->data[1]; /* Output mode */ @@ -378,7 +382,7 @@ /* set ADB state to 'command' */ via[B] = (via[B] & ~ST_MASK) | ST_CMD; - macii_state = sent_first_byte; + macii_state = sending; data_index = 2; restore_flags(flags); @@ -441,7 +445,7 @@ reply_len = 1; prefix_len = 1; reading_reply = 0; - + macii_state = reading; break; @@ -461,15 +465,14 @@ macii_state = reading; break; - case sent_first_byte: + case sending: req = current_req; - /* maybe we're already done (Talk, or Poll)? */ if (data_index >= req->nbytes) { - /* reset to shift in */ - /* If it's a Listen command and we're done, someone's doing weird stuff. */ + /* print an error message if a listen command has no data */ if (((command_byte & 0x0C) == 0x08) - && (console_loglevel == 10)) - printk("macii_interrupt: listen command with no data: %x!\n", + /* && (console_loglevel == 10) */ + && (data_index == 2)) + printk("MacII ADB: listen command with no data: %x!\n", command_byte); /* reset to shift in */ via[ACR] &= ~SR_OUT; @@ -492,42 +495,15 @@ macii_retransmit((command_byte & 0xF0) >> 4); } } else { - /* SR already set to shift out; send byte */ - via[SR] = current_req->data[data_index++]; - /* set state to ST_EVEN (first byte was: ST_CMD) */ - via[B] = (via[B] & ~ST_MASK) | ST_EVEN; - macii_state = sending; - } - break; - - case sending: - req = current_req; - if (data_index >= req->nbytes) { - /* reset to shift in */ - via[ACR] &= ~SR_OUT; - x = via[SR]; - /* set ADB state idle - might get SRQ */ - via[B] = (via[B] & ~ST_MASK) | ST_IDLE; - - req->sent = 1; + via[SR] = req->data[data_index++]; - if (req->reply_expected) { - macii_state = awaiting_reply; + if ( (via[B] & ST_MASK) == ST_CMD ) { + /* just sent the command byte, set to EVEN */ + via[B] = (via[B] & ~ST_MASK) | ST_EVEN; } else { - req->complete = 1; - current_req = req->next; - if (req->done) (*req->done)(req); - macii_state = idle; - if (current_req || retry_req) - macii_start(); - else - macii_retransmit((command_byte & 0xF0) >> 4); + /* invert state bits, toggle ODD/EVEN */ + via[B] ^= ST_MASK; } - } else { - via[SR] = req->data[data_index++]; - - /* invert state bits, toggle ODD/EVEN */ - via[B] ^= ST_MASK; } break; @@ -551,7 +527,7 @@ * on /INT, meaning we missed it :-( */ x = via[SR]; - if (x != 0xFF) printk("macii_interrupt: mistaken timeout/SRQ!\n"); + if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n"); if ((status & TREQ) == (last_status & TREQ)) { /* Not a timeout. Unsolicited SRQ? weird. */ @@ -598,7 +574,7 @@ * byte of timeout packet! * Timeouts are signaled by 4x FF. */ - if (!(status & TREQ) && (x == 0x00)) { /* != 0xFF */ + if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */ /* invert state bits, toggle ODD/EVEN */ via[B] ^= ST_MASK; @@ -646,12 +622,12 @@ need_poll = 0; break; } - + + /* set ADB state to idle */ + via[B] = (via[B] & ~ST_MASK) | ST_IDLE; + /* /IRQ seen, so the ADB controller has data for us */ - if (!(status & TREQ)) { - /* set ADB state to idle */ - via[B] = (via[B] & ~ST_MASK) | ST_IDLE; - + if ((via[B] & TREQ) != 0) { macii_state = reading; reply_buf[0] = command_byte; diff -Nru a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c --- a/drivers/macintosh/via-maciisi.c Wed Jul 24 14:03:39 2002 +++ b/drivers/macintosh/via-maciisi.c Wed Jul 24 14:03:39 2002 @@ -9,7 +9,11 @@ * * Original sources (c) Alan Cox, Paul Mackerras, and others. * - * Rewritten for Unified ADB by David Huggins-Daines */ + * Rewritten for Unified ADB by David Huggins-Daines + * + * 7/13/2000- extensive changes by Andrew McPherson + * Works about 30% of the time now. + */ #include #include @@ -56,6 +60,8 @@ #define ADB_DELAY 150 +#undef DEBUG_MACIISI_ADB + static struct adb_request* current_req = NULL; static struct adb_request* last_req = NULL; static unsigned char maciisi_rbuf[16]; @@ -63,6 +69,8 @@ static int data_index; static int reading_reply; static int reply_len; +static int tmp; +static int need_sync; static enum maciisi_state { idle, @@ -73,12 +81,13 @@ static int maciisi_probe(void); static int maciisi_init(void); static int maciisi_send_request(struct adb_request* req, int sync); +static void maciisi_sync(struct adb_request *req); static int maciisi_write(struct adb_request* req); static void maciisi_interrupt(int irq, void* arg, struct pt_regs* regs); static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs); static int maciisi_init_via(void); static void maciisi_poll(void); -static void maciisi_start(void); +static int maciisi_start(void); struct adb_driver via_maciisi_driver = { "Mac IIsi", @@ -114,63 +123,105 @@ return err; } - if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK, + if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, "ADB", maciisi_interrupt)) { printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB); return -EAGAIN; } - printk("adb: Mac IIsi driver v0.1 for Unified ADB.\n"); + printk("adb: Mac IIsi driver v0.2 for Unified ADB.\n"); return 0; } +/* Flush data from the ADB controller */ static void maciisi_stfu(void) { int status = via[B] & (TIP|TREQ); if (status & TREQ) { +#ifdef DEBUG_MACIISI_ADB printk (KERN_DEBUG "maciisi_stfu called with TREQ high!\n"); +#endif return; } + + udelay(ADB_DELAY); + via[ACR] &= ~SR_OUT; + via[IER] = IER_CLR | SR_INT; - /* start transfer */ - via[B] |= TIP; - while (!(status & TREQ)) { - int poll_timeout = ADB_DELAY * 5; - /* Poll for SR interrupt */ - while (!(via[IFR] & SR_INT) && poll_timeout-- > 0) - status = via[B] & (TIP|TREQ); - via[SR]; /* Clear shift register */ - printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d\n", - status, poll_timeout); - - /* ACK on-off */ - via[B] |= TACK; + udelay(ADB_DELAY); + + status = via[B] & (TIP|TREQ); + + if (!(status & TREQ)) + { + via[B] |= TIP; + + while(1) + { + int poll_timeout = ADB_DELAY * 5; + /* Poll for SR interrupt */ + while (!(via[IFR] & SR_INT) && poll_timeout-- > 0) + status = via[B] & (TIP|TREQ); + + tmp = via[SR]; /* Clear shift register */ +#ifdef DEBUG_MACIISI_ADB + printk(KERN_DEBUG "maciisi_stfu: status %x timeout %d data %x\n", + status, poll_timeout, tmp); +#endif + if(via[B] & TREQ) + break; + + /* ACK on-off */ + via[B] |= TACK; + udelay(ADB_DELAY); + via[B] &= ~TACK; + } + + /* end frame */ + via[B] &= ~TIP; udelay(ADB_DELAY); - via[B] &= ~TACK; } - /* end frame */ - via[B] &= ~TIP; + + via[IER] = IER_SET | SR_INT; } /* All specifically VIA-related initialization goes here */ static int maciisi_init_via(void) { + int i; + /* Set the lines up. We want TREQ as input TACK|TIP as output */ via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; /* Shift register on input */ via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "maciisi_init_via: initial status %x\n", via[B] & (TIP|TREQ)); +#endif + /* Wipe any pending data and int */ + tmp = via[SR]; + /* Enable keyboard interrupts */ + via[IER] = IER_SET | SR_INT; /* Set initial state: idle */ via[B] &= ~(TACK|TIP); - /* Wipe any pending data and int */ - via[SR]; - if (!(via[B] & TREQ)) + /* Clear interrupt bit */ + via[IFR] = SR_INT; + + for(i = 0; i < 60; i++) { + udelay(ADB_DELAY); maciisi_stfu(); - via[IER] = IER_SET | SR_INT; + udelay(ADB_DELAY); + if(via[B] & TREQ) + break; + } + if (i == 60) + printk(KERN_ERR "maciisi_init_via: bus jam?\n"); + maciisi_state = idle; + need_sync = 0; + return 0; } @@ -179,41 +230,76 @@ maciisi_send_request(struct adb_request* req, int sync) { int i; - static int dump_packet = 1; + +#ifdef DEBUG_MACIISI_ADB + static int dump_packet = 0; +#endif if (via == NULL) { req->complete = 1; return -ENXIO; } +#ifdef DEBUG_MACIISI_ADB if (dump_packet) { printk(KERN_DEBUG "maciisi_send_request:"); for (i = 0; i < req->nbytes; i++) { printk(" %.2x", req->data[i]); } - printk("\n"); + printk(" sync %d\n", sync); } +#endif + req->reply_expected = 1; i = maciisi_write(req); if (i) + { + /* Normally, if a packet requires syncing, that happens at the end of + * maciisi_send_request. But if the transfer fails, it will be restarted + * by maciisi_interrupt(). We use need_sync to tell maciisi_interrupt + * when to sync a packet that it sends out. + * + * Suggestions on a better way to do this are welcome. + */ + if(i == -EBUSY && sync) + need_sync = 1; + else + need_sync = 0; return i; - - if (sync) { - while (!req->complete) { - maciisi_poll(); - } } + if(sync) + maciisi_sync(req); + return 0; } +/* Poll the ADB chip until the request completes */ +static void maciisi_sync(struct adb_request *req) +{ + int count = 0; + +#ifdef DEBUG_MACIISI_ADB + printk(KERN_DEBUG "maciisi_sync called\n"); +#endif + + /* If for some reason the ADB chip shuts up on us, we want to avoid an endless loop. */ + while (!req->complete && count++ < 50) { + maciisi_poll(); + } + /* This could be BAD... when the ADB controller doesn't respond + * for this long, it's probably not coming back :-( */ + if(count >= 50) /* Hopefully shouldn't happen */ + printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); +} + /* Enqueue a request, and run the queue if possible */ static int maciisi_write(struct adb_request* req) { unsigned long flags; + int i; - printk(KERN_DEBUG "maciisi_write called, state=%d ifr=%x\n", maciisi_state, via[IFR]); /* We will accept CUDA packets - the VIA sends them to us, so it figures that we should be able to send them to it */ if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { @@ -225,7 +311,9 @@ req->sent = 0; req->complete = 0; req->reply_len = 0; - save_flags(flags); cli(); + + save_flags(flags); + cli(); if (current_req) { last_req->next = req; @@ -235,44 +323,68 @@ last_req = req; } if (maciisi_state == idle) - maciisi_start(); + { + i = maciisi_start(); + if(i != 0) + { + restore_flags(flags); + return i; + } + } else + { +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state); +#endif + restore_flags(flags); + return -EBUSY; + } restore_flags(flags); + return 0; } -static void +static int maciisi_start(void) { struct adb_request* req; int status; - printk(KERN_DEBUG "maciisi_start called, state=%d, ifr=%x\n", maciisi_state, via[IFR]); +#ifdef DEBUG_MACIISI_ADB + status = via[B] & (TIP | TREQ); + + printk(KERN_DEBUG "maciisi_start called, state=%d, status=%x, ifr=%x\n", maciisi_state, status, via[IFR]); +#endif + if (maciisi_state != idle) { /* shouldn't happen */ printk(KERN_ERR "maciisi_start: maciisi_start called when driver busy!\n"); - return; + return -EBUSY; } req = current_req; if (req == NULL) - return; + return -EINVAL; status = via[B] & (TIP|TREQ); if (!(status & TREQ)) { - /* Bus is busy, set up for reading */ +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "maciisi_start: bus busy - aborting\n"); - return; +#endif + return -EBUSY; } /* Okay, send */ +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "maciisi_start: sending\n"); +#endif /* Set state to active */ via[B] |= TIP; /* ACK off */ via[B] &= ~TACK; + /* Delay */ + udelay(ADB_DELAY); /* Shift out and send */ via[ACR] |= SR_OUT; via[SR] = req->data[0]; @@ -280,6 +392,8 @@ /* ACK on */ via[B] |= TACK; maciisi_state = sending; + + return 0; } void @@ -292,6 +406,9 @@ if (via[IFR] & SR_INT) { maciisi_interrupt(0, 0, 0); } + else /* avoid calling this function too quickly in a loop */ + udelay(ADB_DELAY); + restore_flags(flags); } @@ -303,31 +420,44 @@ { int status; struct adb_request *req; - static int dump_reply = 1; +#ifdef DEBUG_MACIISI_ADB + static int dump_reply = 0; +#endif + int i; + unsigned long flags; + + save_flags(flags); + cli(); + + status = via[B] & (TIP|TREQ); +#ifdef DEBUG_MACIISI_ADB + printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]); +#endif if (!(via[IFR] & SR_INT)) { /* Shouldn't happen, we hope */ - printk(KERN_DEBUG "maciisi_interrupt: called without interrupt flag set\n"); + printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n"); + restore_flags(flags); return; } - status = via[B] & (TIP|TREQ); - printk(KERN_DEBUG "state %d status %x ifr %x\n", maciisi_state, status, via[IFR]); + /* Clear the interrupt */ + /* via[IFR] = SR_INT; */ switch_start: switch (maciisi_state) { case idle: - printk(KERN_DEBUG "maciisi_interrupt: state=idle, status %x\n", status); if (status & TIP) - printk(KERN_DEBUG "maciisi_interrupt: state is idle but TIP asserted!\n"); + printk(KERN_ERR "maciisi_interrupt: state is idle but TIP asserted!\n"); - udelay(ADB_DELAY); + if(!reading_reply) + udelay(ADB_DELAY); /* Shift in */ via[ACR] &= ~SR_OUT; /* Signal start of frame */ via[B] |= TIP; /* Clear the interrupt (throw this value on the floor, it's useless) */ - via[SR]; + tmp = via[SR]; /* ACK adb chip, high-low */ via[B] |= TACK; udelay(ADB_DELAY); @@ -337,37 +467,39 @@ if (reading_reply) { reply_ptr = current_req->reply; } else { - printk(KERN_DEBUG "maciisi_interrupt: received unsolicited packet\n"); reply_ptr = maciisi_rbuf; } break; case sending: - printk(KERN_DEBUG "maciisi_interrupt: state=sending, status=%x\n", status); - /* Clear interrupt */ - via[SR]; + /* via[SR]; */ /* Set ACK off */ via[B] &= ~TACK; req = current_req; if (!(status & TREQ)) { /* collision */ - printk(KERN_DEBUG "maciisi_interrupt: send collision\n"); + printk(KERN_ERR "maciisi_interrupt: send collision\n"); /* Set idle and input */ - via[B] &= ~TIP; via[ACR] &= ~SR_OUT; + tmp = via[SR]; + via[B] &= ~TIP; /* Must re-send */ reading_reply = 0; reply_len = 0; maciisi_state = idle; + udelay(ADB_DELAY); /* process this now, because the IFR has been cleared */ goto switch_start; } + udelay(ADB_DELAY); + if (data_index >= req->nbytes) { /* Sent the whole packet, put the bus back in idle state */ /* Shift in, we are about to read a reply (hopefully) */ via[ACR] &= ~SR_OUT; + tmp = via[SR]; /* End of frame */ via[B] &= ~TIP; req->sent = 1; @@ -380,13 +512,19 @@ current_req = req->next; if (req->done) (*req->done)(req); + /* Do any queued requests now */ + i = maciisi_start(); + if(i == 0 && need_sync) { + /* Packet needs to be synced */ + maciisi_sync(current_req); + } + if(i != -EBUSY) + need_sync = 0; } } else { /* Sending more stuff */ /* Shift out */ via[ACR] |= SR_OUT; - /* Delay */ - udelay(ADB_DELAY); /* Write */ via[SR] = req->data[data_index++]; /* Signal 'byte ready' */ @@ -395,18 +533,24 @@ break; case reading: - printk(KERN_DEBUG "maciisi_interrupt: state=reading, status=%x\n", status); /* Shift in */ - via[ACR] &= ~SR_OUT; + /* via[ACR] &= ~SR_OUT; */ /* Not in 2.2 */ if (reply_len++ > 16) { printk(KERN_ERR "maciisi_interrupt: reply too long, aborting read\n"); via[B] |= TACK; udelay(ADB_DELAY); via[B] &= ~(TACK|TIP); maciisi_state = idle; - maciisi_start(); + i = maciisi_start(); + if(i == 0 && need_sync) { + /* Packet needs to be synced */ + maciisi_sync(current_req); + } + if(i != -EBUSY) + need_sync = 0; break; } + /* Read data */ *reply_ptr++ = via[SR]; status = via[B] & (TIP|TREQ); /* ACK on/off */ @@ -418,6 +562,8 @@ /* end of frame */ via[B] &= ~TIP; + tmp = via[SR]; /* That's what happens in 2.2 */ + udelay(ADB_DELAY); /* Give controller time to recover */ /* end of packet, deal with it */ if (reading_reply) { @@ -434,6 +580,7 @@ memmove(req->reply, req->reply + 2, req->reply_len); } } +#ifdef DEBUG_MACIISI_ADB if (dump_reply) { int i; printk(KERN_DEBUG "maciisi_interrupt: reply is "); @@ -441,6 +588,7 @@ printk(" %.2x", req->reply[i]); printk("\n"); } +#endif req->complete = 1; current_req = req->next; if (req->done) @@ -453,34 +601,62 @@ maciisi_state = idle; status = via[B] & (TIP|TREQ); if (!(status & TREQ)) { - /* Timeout?! */ + /* Timeout?! More likely, another packet coming in already */ +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "extra data after packet: status %x ifr %x\n", status, via[IFR]); - maciisi_stfu(); +#endif +#if 0 + udelay(ADB_DELAY); + via[B] |= TIP; + + maciisi_state = reading; + reading_reply = 0; + reply_ptr = maciisi_rbuf; +#else + /* Process the packet now */ + reading_reply = 0; + goto switch_start; +#endif + /* We used to do this... but the controller might actually have data for us */ + /* maciisi_stfu(); */ + } + else { + /* Do any queued requests now if possible */ + i = maciisi_start(); + if(i == 0 && need_sync) { + /* Packet needs to be synced */ + maciisi_sync(current_req); + } + if(i != -EBUSY) + need_sync = 0; } - /* Do any queued requests now if possible */ - maciisi_start(); break; default: printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state); } + restore_flags(flags); } static void maciisi_input(unsigned char *buf, int nb, struct pt_regs *regs) { +#ifdef DEBUG_MACIISI_ADB int i; +#endif switch (buf[0]) { case ADB_PACKET: adb_input(buf+2, nb-2, regs, buf[1] & 0x40); break; default: +#ifdef DEBUG_MACIISI_ADB printk(KERN_DEBUG "data from IIsi ADB (%d bytes):", nb); for (i = 0; i < nb; ++i) printk(" %.2x", buf[i]); printk("\n"); - +#endif + break; } } diff -Nru a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c --- a/drivers/macintosh/via-pmu68k.c Wed Jul 24 14:03:36 2002 +++ b/drivers/macintosh/via-pmu68k.c Wed Jul 24 14:03:36 2002 @@ -120,6 +120,8 @@ static void pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs); static void set_volume(int level); +static void pmu_enable_backlight(int on); +static void pmu_set_brightness(int level); struct adb_driver via_pmu_driver = { "68K PMU", @@ -746,7 +748,7 @@ #define LEVEL_TO_BRIGHT(lev) ((lev) < 1? 0x7f: 0x4a - ((lev) << 1)) -void +static void pmu_enable_backlight(int on) { struct adb_request req; @@ -780,7 +782,7 @@ backlight_enabled = on; } -void +static void pmu_set_brightness(int level) { int bright; diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c --- a/drivers/md/linear.c Wed Jul 24 14:03:37 2002 +++ b/drivers/md/linear.c Wed Jul 24 14:03:37 2002 @@ -193,11 +193,11 @@ static mdk_personality_t linear_personality= { - name: "linear", - make_request: linear_make_request, - run: linear_run, - stop: linear_stop, - status: linear_status, + .name = "linear", + .make_request = linear_make_request, + .run = linear_run, + .stop = linear_stop, + .status = linear_status, }; static int __init linear_init (void) diff -Nru a/drivers/md/lvm.c b/drivers/md/lvm.c --- a/drivers/md/lvm.c Wed Jul 24 14:03:38 2002 +++ b/drivers/md/lvm.c Wed Jul 24 14:03:38 2002 @@ -872,17 +872,6 @@ return -EFAULT; break; - - case BLKFLSBUF: - /* flush buffer cache */ - if (!capable(CAP_SYS_ADMIN)) return -EACCES; - - P_IOCTL("BLKFLSBUF\n"); - - fsync_bdev(inode->i_bdev); - invalidate_buffers(inode->i_rdev); - break; - case HDIO_GETGEO: /* get disk geometry */ P_IOCTL("%s -- lvm_blk_ioctl -- HDIO_GETGEO\n", lvm_name); diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Wed Jul 24 14:03:37 2002 +++ b/drivers/md/md.c Wed Jul 24 14:03:37 2002 @@ -118,14 +118,14 @@ static struct gendisk md_gendisk= { - major: MD_MAJOR, - major_name: "md", - minor_shift: 0, - part: md_hd_struct, - sizes: md_size, - nr_real: MAX_MD_DEVS, - next: NULL, - fops: &md_fops, + .major = MD_MAJOR, + .major_name = "md", + .minor_shift = 0, + .part = md_hd_struct, + .sizes = md_size, + .nr_real = MAX_MD_DEVS, + .next = NULL, + .fops = &md_fops, }; /* @@ -847,7 +847,7 @@ MD_BUG(); return; } - rdev = list_entry(&mddev->disks.next, mdk_rdev_t, same_set); + rdev = list_entry(mddev->disks.next, mdk_rdev_t, same_set); sb = rdev->sb; memset(sb, 0, sizeof(*sb)); @@ -1044,8 +1044,6 @@ } INIT_LIST_HEAD(&rdev->same_set); - if (rdev->faulty && rdev->sb) - free_disk_sb(rdev); return rdev; abort_free: @@ -2241,28 +2239,6 @@ autostart_arrays(); goto done; #endif - - case BLKGETSIZE: /* Return device size */ - if (!arg) { - err = -EINVAL; - MD_BUG(); - goto abort; - } - err = put_user(md_hd_struct[minor].nr_sects, - (unsigned long *) arg); - goto done; - - case BLKGETSIZE64: /* Return device size */ - err = put_user((u64)md_hd_struct[minor].nr_sects << 9, - (u64 *) arg); - goto done; - - case BLKFLSBUF: - case BLKBSZGET: - case BLKBSZSET: - err = blk_ioctl(inode->i_bdev, cmd, arg); - goto abort; - default:; } @@ -2386,7 +2362,7 @@ (short *) &loc->cylinders); if (err) goto abort_unlock; - err = put_user (get_start_sect(dev), + err = put_user (get_start_sect(inode->i_bdev), (long *) &loc->start); goto done_unlock; } @@ -2498,10 +2474,10 @@ static struct block_device_operations md_fops = { - owner: THIS_MODULE, - open: md_open, - release: md_release, - ioctl: md_ioctl, + .owner = THIS_MODULE, + .open = md_open, + .release = md_release, + .ioctl = md_ioctl, }; @@ -3189,9 +3165,9 @@ } struct notifier_block md_notifier = { - notifier_call: md_notify_reboot, - next: NULL, - priority: INT_MAX, /* before any real devices */ + .notifier_call = md_notify_reboot, + .next = NULL, + .priority = INT_MAX, /* before any real devices */ }; static void md_geninit(void) diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c --- a/drivers/md/multipath.c Wed Jul 24 14:03:38 2002 +++ b/drivers/md/multipath.c Wed Jul 24 14:03:38 2002 @@ -562,14 +562,14 @@ static mdk_personality_t multipath_personality= { - name: "multipath", - make_request: multipath_make_request, - run: multipath_run, - stop: multipath_stop, - status: multipath_status, - error_handler: multipath_error, - hot_add_disk: multipath_add_disk, - hot_remove_disk:multipath_remove_disk, + .name = "multipath", + .make_request = multipath_make_request, + .run = multipath_run, + .stop = multipath_stop, + .status = multipath_status, + .error_handler = multipath_error, + .hot_add_disk = multipath_add_disk, + .hot_remove_disk= multipath_remove_disk, }; static int __init multipath_init (void) diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c --- a/drivers/md/raid0.c Wed Jul 24 14:03:38 2002 +++ b/drivers/md/raid0.c Wed Jul 24 14:03:38 2002 @@ -366,11 +366,11 @@ static mdk_personality_t raid0_personality= { - name: "raid0", - make_request: raid0_make_request, - run: raid0_run, - stop: raid0_stop, - status: raid0_status, + .name = "raid0", + .make_request = raid0_make_request, + .run = raid0_run, + .stop = raid0_stop, + .status = raid0_status, }; static int __init raid0_init (void) diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c Wed Jul 24 14:03:35 2002 +++ b/drivers/md/raid1.c Wed Jul 24 14:03:35 2002 @@ -1346,18 +1346,18 @@ static mdk_personality_t raid1_personality = { - name: "raid1", - make_request: make_request, - run: run, - stop: stop, - status: status, - error_handler: error, - hot_add_disk: raid1_add_disk, - hot_remove_disk:raid1_remove_disk, - spare_write: raid1_spare_write, - spare_inactive: raid1_spare_inactive, - spare_active: raid1_spare_active, - sync_request: sync_request + .name = "raid1", + .make_request = make_request, + .run = run, + .stop = stop, + .status = status, + .error_handler = error, + .hot_add_disk = raid1_add_disk, + .hot_remove_disk= raid1_remove_disk, + .spare_write = raid1_spare_write, + .spare_inactive = raid1_spare_inactive, + .spare_active = raid1_spare_active, + .sync_request = sync_request, }; static int __init raid_init(void) diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c Wed Jul 24 14:03:36 2002 +++ b/drivers/md/raid5.c Wed Jul 24 14:03:36 2002 @@ -1820,18 +1820,18 @@ static mdk_personality_t raid5_personality= { - name: "raid5", - make_request: make_request, - run: run, - stop: stop, - status: status, - error_handler: error, - hot_add_disk: raid5_add_disk, - hot_remove_disk:raid5_remove_disk, - spare_write: raid5_spare_write, - spare_inactive: raid5_spare_inactive, - spare_active: raid5_spare_active, - sync_request: sync_request + .name = "raid5", + .make_request = make_request, + .run = run, + .stop = stop, + .status = status, + .error_handler = error, + .hot_add_disk = raid5_add_disk, + .hot_remove_disk= raid5_remove_disk, + .spare_write = raid5_spare_write, + .spare_inactive = raid5_spare_inactive, + .spare_active = raid5_spare_active, + .sync_request = sync_request, }; static int __init raid5_init (void) diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Wed Jul 24 14:03:37 2002 +++ b/drivers/message/fusion/mptscsih.c Wed Jul 24 14:03:37 2002 @@ -3576,7 +3576,7 @@ */ int -mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip) +mptscsih_bios_param(Disk * disk, struct block_device *dev, int *ip) { int size; diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h Wed Jul 24 14:03:39 2002 +++ b/drivers/message/fusion/mptscsih.h Wed Jul 24 14:03:39 2002 @@ -201,7 +201,7 @@ extern int x_scsi_old_abort(Scsi_Cmnd *); extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); #endif -extern int x_scsi_bios_param(Disk *, kdev_t, int *); +extern int x_scsi_bios_param(Disk *, struct block_device *, int *); extern void x_scsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *); extern void x_scsi_taskmgmt_bh(void *); diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Wed Jul 24 14:03:39 2002 +++ b/drivers/message/i2o/i2o_block.c Wed Jul 24 14:03:39 2002 @@ -1050,13 +1050,7 @@ return -EBUSY; } - for( i = 15; i>=0 ; i--) - { - int m = minor+i; - invalidate_device(mk_kdev(MAJOR_NR, m), 1); - i2ob_gendisk.part[m].start_sect = 0; - i2ob_gendisk.part[m].nr_sects = 0; - } + wipe_partitions(mk_kdev(MAJOR_NR, minor), 1); /* * Do a physical check and then reconfigure @@ -1089,7 +1083,7 @@ int u = minor(inode->i_rdev) & 0xF0; i2o_block_biosparam(i2ob_sizes[u]<<1, &g.cylinders, &g.heads, &g.sectors); - g.start = get_start_sect(inode->i_rdev); + g.start = get_start_sect(inode->i_bdev); return copy_to_user((void *)arg, &g, sizeof(g)) ? -EFAULT : 0; } @@ -1099,14 +1093,6 @@ return -EACCES; return do_i2ob_revalidate(inode->i_rdev,1); - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKFLSBUF: - case BLKROSET: - case BLKROGET: - case BLKPG: - return blk_ioctl(inode->i_bdev, cmd, arg); - default: return -EINVAL; } @@ -1815,7 +1801,6 @@ * Now fill in the boiler plate */ - blk_size[MAJOR_NR] = i2ob_sizes; blk_dev[MAJOR_NR].queue = i2ob_get_queue; blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request); diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c Wed Jul 24 14:03:36 2002 +++ b/drivers/message/i2o/i2o_scsi.c Wed Jul 24 14:03:36 2002 @@ -902,7 +902,7 @@ * This is anyones guess quite frankly. */ -int i2o_scsi_bios_param(Disk * disk, kdev_t dev, int *ip) +int i2o_scsi_bios_param(Disk * disk, struct block_device *dev, int *ip) { int size; diff -Nru a/drivers/message/i2o/i2o_scsi.h b/drivers/message/i2o/i2o_scsi.h --- a/drivers/message/i2o/i2o_scsi.h Wed Jul 24 14:03:38 2002 +++ b/drivers/message/i2o/i2o_scsi.h Wed Jul 24 14:03:38 2002 @@ -20,7 +20,7 @@ extern int i2o_scsi_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); extern int i2o_scsi_abort(Scsi_Cmnd *); extern int i2o_scsi_reset(Scsi_Cmnd *, unsigned int); -extern int i2o_scsi_bios_param(Disk *, kdev_t, int *); +extern int i2o_scsi_bios_param(Disk *, struct block_device *, int *); extern void i2o_scsi_setup(char *str, int *ints); extern int i2o_scsi_release(struct Scsi_Host *host); diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Wed Jul 24 14:03:37 2002 +++ b/drivers/mtd/ftl.c Wed Jul 24 14:03:37 2002 @@ -880,9 +880,6 @@ DEBUG(0, "ftl_cs: ftl_close(%d)\n", minor); - /* Flush all writes */ - invalidate_device(inode->i_rdev, 1); - /* Wait for any pending erase operations to complete */ if (part->mtd->sync) part->mtd->sync(part->mtd); @@ -1126,22 +1123,11 @@ put_user(1, (char *)&geo->heads); put_user(8, (char *)&geo->sectors); put_user((sect>>3), (short *)&geo->cylinders); - put_user(get_start_sect(inode->i_rdev), (u_long *)&geo->start); - break; - case BLKGETSIZE: - ret = put_user(ftl_hd[minor].nr_sects, (unsigned long *)arg); - break; - case BLKGETSIZE64: - ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg); + put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start); break; case BLKRRPART: ret = ftl_reread_partitions(inode->i_rdev); break; - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - ret = blk_ioctl(inode->i_bdev, cmd, arg); - break; default: ret = -EINVAL; } @@ -1157,25 +1143,20 @@ static int ftl_reread_partitions(kdev_t dev) { - int minor = minor(dev); - partition_t *part = myparts[minor >> 4]; - int res; - - DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor); - if ((atomic_read(&part->open) > 1)) { - return -EBUSY; - } - - res = wipe_partitions(dev); - if (res) - goto leave; - - scan_header(part); - - register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART, - &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); - - return res; + int minor = minor(dev); + partition_t *part = myparts[minor >> 4]; + kdev_t device = mk_kdev(MAJOR_NR, minor & ~15); + int res = dev_lock_part(device); + if (rec < 0) + return res; + res = wipe_partitions(device); + if (!res) { + scan_header(part); + grok_partitions(device, + le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE); + } + dev_unlock_part(device); + return res; } /*====================================================================== @@ -1285,13 +1266,13 @@ partition->mtd = mtd; - if ((scan_header(partition) == 0) && - (build_maps(partition) == 0)) { - + if ((scan_header(partition) == 0) && (build_maps(partition) == 0)) { partition->state = FTL_FORMATTED; atomic_set(&partition->open, 0); myparts[device] = partition; - ftl_reread_partitions(device << 4); + register_disk(&ftl_gendisk, mk_kdev(MAJOR_NR, device << 4), + MAX_PART, &ftl_blk_fops, + le32_to_cpu(partition->header.FormattedSize)/SECTOR_SIZE); #ifdef PCMCIA_DEBUG printk(KERN_INFO "ftl_cs: opening %d kb FTL partition\n", le32_to_cpu(partition->header.FormattedSize) >> 10); diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Wed Jul 24 14:03:37 2002 +++ b/drivers/mtd/mtdblock.c Wed Jul 24 14:03:37 2002 @@ -354,8 +354,6 @@ if (inode == NULL) release_return(-ENODEV); - invalidate_device(inode->i_rdev, 1); - dev = minor(inode->i_rdev); mtdblk = mtdblks[dev]; diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c --- a/drivers/mtd/mtdblock_ro.c Wed Jul 24 14:03:38 2002 +++ b/drivers/mtd/mtdblock_ro.c Wed Jul 24 14:03:38 2002 @@ -76,8 +76,6 @@ if (inode == NULL) release_return(-ENODEV); - invalidate_device(inode->i_rdev, 1); - dev = minor(inode->i_rdev); mtd = __get_mtd_device(NULL, dev); diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Wed Jul 24 14:03:35 2002 +++ b/drivers/mtd/nftlcore.c Wed Jul 24 14:03:35 2002 @@ -115,7 +115,6 @@ #endif /* linux stuff */ - nftl->usecount = 0; nftl->cylinders = 1024; nftl->heads = 16; @@ -153,8 +152,9 @@ #if LINUX_VERSION_CODE < 0x20328 resetup_one_dev(&nftl_gendisk, firstfree); #else - grok_partitions(mk_kdev(MAJOR_NR,firstfree<nr_sects); + register_disk(&nftl_gendisk, + mk_kdev(MAJOR_NR,firstfree<nr_sects); #endif } @@ -787,7 +787,7 @@ g.heads = nftl->heads; g.sectors = nftl->sectors; g.cylinders = nftl->cylinders; - g.start = get_start_sect(inode->i_rdev); + g.start = get_start_sect(inode->i_bdev); return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; } case BLKFLSBUF: @@ -800,29 +800,18 @@ case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (nftl->usecount > 1) return -EBUSY; - /* - * We have to flush all buffers and invalidate caches, - * or we won't be able to re-use the partitions, - * if there was a change and we don't want to reboot - */ - res = wipe_partitions(inode->i_rdev); + { + kdev_t device = mk_kdev(MAJOR_NR, + minor(inode->i_rdev) & -(1<i_rdev, nftl->nr_sects); - + grok_partitions(device, nftl->nr_sects); + dev_unlock_part(device); + } return res; - -#if (LINUX_VERSION_CODE < 0x20303) - RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ -#else - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_bdev, cmd, arg); -#endif - default: return -EINVAL; } @@ -955,7 +944,6 @@ return -EROFS; #endif /* !CONFIG_NFTL_RW */ - thisNFTL->usecount++; if (!get_mtd_device(thisNFTL->mtd, -1)) return /* -E'SBUGGEREDOFF */ -ENXIO; @@ -970,11 +958,8 @@ DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); - invalidate_device(inode->i_rdev, 1); - if (thisNFTL->mtd->sync) thisNFTL->mtd->sync(thisNFTL->mtd); - thisNFTL->usecount--; put_mtd_device(thisNFTL->mtd); diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c --- a/drivers/net/7990.c Wed Jul 24 14:03:39 2002 +++ b/drivers/net/7990.c Wed Jul 24 14:03:39 2002 @@ -569,7 +569,7 @@ volatile u16 *mcast_table = (u16 *)&ib->filter; struct dev_mc_list *dmi=dev->mc_list; char *addrs; - int i, j, bit, byte; + int i; u32 crc; /* set all multicast bits */ diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c --- a/drivers/net/8139cp.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/8139cp.c Wed Jul 24 14:03:38 2002 @@ -926,13 +926,15 @@ static void cp_stop_hw (struct cp_private *cp) { + struct net_device *dev = cp->dev; + cpw16(IntrMask, 0); cpr16(IntrMask); cpw8(Cmd, 0); cpw16(CpCmd, 0); cpr16(CpCmd); cpw16(IntrStatus, ~(cpr16(IntrStatus))); - synchronize_irq(); + synchronize_irq(dev->irq); udelay(10); cp->rx_tail = 0; diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c Wed Jul 24 14:03:35 2002 +++ b/drivers/net/8139too.c Wed Jul 24 14:03:35 2002 @@ -2130,7 +2130,9 @@ spin_unlock_irqrestore (&tp->lock, flags); - synchronize_irq (); + /* TODO: isn't this code racy? we synchronize the IRQ and then free it, */ + /* but another IRQ could've happened in between the sync and free */ + synchronize_irq (dev->irq); free_irq (dev->irq, dev); rtl8139_tx_clear (tp); diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c --- a/drivers/net/82596.c Wed Jul 24 14:03:36 2002 +++ b/drivers/net/82596.c Wed Jul 24 14:03:36 2002 @@ -64,7 +64,7 @@ #include static char version[] __initdata = - "82596.c $Revision: 1.4 $\n"; + "82596.c $Revision: 1.5 $\n"; /* DEBUG flags */ @@ -421,7 +421,7 @@ while (--delcnt && lp->iscp.stat) udelay(10); if (!delcnt) { - printk("%s: %s, status %4.4x, cmd %4.4x.\n", + printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n", dev->name, str, lp->scb.status, lp->scb.command); return -1; } @@ -435,7 +435,7 @@ while (--delcnt && lp->scb.command) udelay(10); if (!delcnt) { - printk("%s: %s, status %4.4x, cmd %4.4x.\n", + printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n", dev->name, str, lp->scb.status, lp->scb.command); return -1; } @@ -444,6 +444,21 @@ } +static inline int wait_cfg(struct net_device *dev, struct i596_cmd *cmd, int delcnt, char *str) +{ + volatile struct i596_cmd *c = cmd; + + while (--delcnt && c->command) + udelay(10); + if (!delcnt) { + printk(KERN_ERR "%s: %s.\n", dev->name, str); + return -1; + } + else + return 0; +} + + static void i596_display_data(struct net_device *dev) { struct i596_private *lp = (struct i596_private *) dev->priv; @@ -451,37 +466,37 @@ struct i596_rfd *rfd; struct i596_rbd *rbd; - printk("lp and scp at %p, .sysbus = %08lx, .iscp = %p\n", + printk(KERN_ERR "lp and scp at %p, .sysbus = %08lx, .iscp = %p\n", &lp->scp, lp->scp.sysbus, lp->scp.iscp); - printk("iscp at %p, iscp.stat = %08lx, .scb = %p\n", + printk(KERN_ERR "iscp at %p, iscp.stat = %08lx, .scb = %p\n", &lp->iscp, lp->iscp.stat, lp->iscp.scb); - printk("scb at %p, scb.status = %04x, .command = %04x," + printk(KERN_ERR "scb at %p, scb.status = %04x, .command = %04x," " .cmd = %p, .rfd = %p\n", &lp->scb, lp->scb.status, lp->scb.command, lp->scb.cmd, lp->scb.rfd); - printk(" errors: crc %lx, align %lx, resource %lx," + printk(KERN_ERR " errors: crc %lx, align %lx, resource %lx," " over %lx, rcvdt %lx, short %lx\n", lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err, lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err); cmd = lp->cmd_head; while (cmd != I596_NULL) { - printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n", + printk(KERN_ERR "cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n", cmd, cmd->status, cmd->command, cmd->b_next); cmd = cmd->v_next; } rfd = lp->rfd_head; - printk("rfd_head = %p\n", rfd); + printk(KERN_ERR "rfd_head = %p\n", rfd); do { - printk (" %p .stat %04x, .cmd %04x, b_next %p, rbd %p," + printk(KERN_ERR " %p .stat %04x, .cmd %04x, b_next %p, rbd %p," " count %04x\n", rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd, rfd->count); rfd = rfd->v_next; } while (rfd != lp->rfd_head); rbd = lp->rbd_head; - printk("rbd_head = %p\n", rbd); + printk(KERN_ERR "rbd_head = %p\n", rbd); do { - printk(" %p .count %04x, b_next %p, b_data %p, size %04x\n", + printk(KERN_ERR " %p .count %04x, b_next %p, b_data %p, size %04x\n", rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); rbd = rbd->v_next; } while (rbd != lp->rbd_head); @@ -492,11 +507,23 @@ static void i596_error(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; - volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; +#ifdef ENABLE_MVME16x_NET + if (MACH_IS_MVME16x) { + volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; + + pcc2[0x28] = 1; + pcc2[0x2b] = 0x1d; + } +#endif +#ifdef ENABLE_BVME6000_NET + if (MACH_IS_BVME6000) { + volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG; - pcc2[0x28] = 1; - pcc2[0x2b] = 0x1d; - printk("%s: Error interrupt\n", dev->name); + *ethirq = 1; + *ethirq = 3; + } +#endif + printk(KERN_ERR "%s: Error interrupt\n", dev->name); i596_display_data(dev); } #endif @@ -660,7 +687,14 @@ lp->cmd_head = lp->scb.cmd = I596_NULL; - DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name)); +#ifdef ENABLE_BVME6000_NET + if (MACH_IS_BVME6000) { + lp->scb.t_on = 7 * 25; + lp->scb.t_off = 1 * 25; + } +#endif + + DEB(DEB_INIT,printk(KERN_DEBUG "%s: starting i82596.\n", dev->name)); #if defined(ENABLE_APRICOT) (void) inb(ioaddr + 0x10); @@ -670,7 +704,7 @@ if (wait_istat(dev,lp,1000,"initialization timed out")) goto failed; - DEB(DEB_INIT,printk("%s: i82596 initialization successful\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: i82596 initialization successful\n", dev->name)); /* Ensure rx frame/buffer descriptors are tidy */ rebuild_rx_bufs(dev); @@ -694,17 +728,17 @@ #endif - DEB(DEB_INIT,printk("%s: queuing CmdConfigure\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdConfigure\n", dev->name)); memcpy(lp->cf_cmd.i596_config, init_setup, 14); lp->cf_cmd.cmd.command = CmdConfigure; i596_add_cmd(dev, &lp->cf_cmd.cmd); - DEB(DEB_INIT,printk("%s: queuing CmdSASetup\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name)); memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); lp->sa_cmd.cmd.command = CmdSASetup; i596_add_cmd(dev, &lp->sa_cmd.cmd); - DEB(DEB_INIT,printk("%s: queuing CmdTDR\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name)); lp->tdr_cmd.cmd.command = CmdTDR; i596_add_cmd(dev, &lp->tdr_cmd.cmd); @@ -714,7 +748,7 @@ spin_unlock_irqrestore (&lp->lock, flags); goto failed; } - DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name)); lp->scb.command = RX_START; CA(dev); @@ -722,11 +756,11 @@ if (wait_cmd(dev,lp,1000,"RX_START not processed")) goto failed; - DEB(DEB_INIT,printk("%s: Receive unit started OK\n", dev->name)); + DEB(DEB_INIT,printk(KERN_DEBUG "%s: Receive unit started OK\n", dev->name)); return 0; failed: - printk("%s: Failed to initialise 82596\n", dev->name); + printk(KERN_CRIT "%s: Failed to initialise 82596\n", dev->name); MPU_PORT(dev, PORT_RESET, 0); return -1; } @@ -738,7 +772,7 @@ struct i596_rbd *rbd; int frames = 0; - DEB(DEB_RXFRAME,printk ("i596_rx(), rfd_head %p, rbd_head %p\n", + DEB(DEB_RXFRAME,printk(KERN_DEBUG "i596_rx(), rfd_head %p, rbd_head %p\n", lp->rfd_head, lp->rbd_head)); rfd = lp->rfd_head; /* Ref next frame to check */ @@ -749,11 +783,11 @@ else if (rfd->rbd == lp->rbd_head->b_addr) rbd = lp->rbd_head; else { - printk("%s: rbd chain broken!\n", dev->name); + printk(KERN_CRIT "%s: rbd chain broken!\n", dev->name); /* XXX Now what? */ rbd = I596_NULL; } - DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %p, rfd.stat %04x\n", + DEB(DEB_RXFRAME, printk(KERN_DEBUG " rfd %p, rfd.rbd %p, rfd.stat %04x\n", rfd, rfd->rbd, rfd->stat)); if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) { @@ -794,7 +828,7 @@ memory_squeeze: if (skb == NULL) { /* XXX tulip.c can defer packets here!! */ - printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); + printk(KERN_WARNING "%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; } else { @@ -817,7 +851,7 @@ } } else { - DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n", + DEB(DEB_ERRORS, printk(KERN_DEBUG "%s: Error, rfd.stat = 0x%04x\n", dev->name, rfd->stat)); lp->stats.rx_errors++; if ((rfd->stat) & 0x0001) @@ -861,7 +895,7 @@ rfd = lp->rfd_head; } - DEB(DEB_RXFRAME,printk ("frames %d\n", frames)); + DEB(DEB_RXFRAME,printk(KERN_DEBUG "frames %d\n", frames)); return 0; } @@ -904,7 +938,7 @@ { unsigned long flags; - DEB(DEB_RESET,printk("i596_reset\n")); + DEB(DEB_RESET,printk(KERN_DEBUG "i596_reset\n")); spin_lock_irqsave (&lp->lock, flags); @@ -932,7 +966,7 @@ int ioaddr = dev->base_addr; unsigned long flags; - DEB(DEB_ADDCMD,printk("i596_add_cmd\n")); + DEB(DEB_ADDCMD,printk(KERN_DEBUG "i596_add_cmd\n")); cmd->status = 0; cmd->command |= (CMD_EOL | CMD_INTR); @@ -961,7 +995,7 @@ if (tickssofar < ticks_limit) return; - printk("%s: command unit timed out, status resetting.\n", dev->name); + printk(KERN_NOTICE "%s: command unit timed out, status resetting.\n", dev->name); i596_reset(dev, lp, ioaddr); } @@ -971,10 +1005,10 @@ { int res = 0; - DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq)); + DEB(DEB_OPEN,printk(KERN_DEBUG "%s: i596_open() irq %d.\n", dev->name, dev->irq)); if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { - printk("%s: IRQ %d not free\n", dev->name, dev->irq); + printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq); return -EAGAIN; } #ifdef ENABLE_MVME16x_NET @@ -1004,19 +1038,19 @@ int ioaddr = dev->base_addr; /* Transmitter timeout, serious problems. */ - DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n", + DEB(DEB_ERRORS,printk(KERN_ERR "%s: transmit timed out, status resetting.\n", dev->name)); lp->stats.tx_errors++; /* Try to restart the adaptor */ if (lp->last_restart == lp->stats.tx_packets) { - DEB(DEB_ERRORS,printk ("Resetting board.\n")); + DEB(DEB_ERRORS,printk(KERN_ERR "Resetting board.\n")); /* Shutdown and restart */ i596_reset (dev, lp, ioaddr); } else { /* Issue a channel attention signal */ - DEB(DEB_ERRORS,printk ("Kicking board.\n")); + DEB(DEB_ERRORS,printk(KERN_ERR "Kicking board.\n")); lp->scb.command = CUC_START | RX_START; CA (dev); lp->last_restart = lp->stats.tx_packets; @@ -1035,7 +1069,7 @@ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; dev->trans_start = jiffies; - DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%x) called\n", dev->name, + DEB(DEB_STARTTX,printk(KERN_DEBUG "%s: i596_start_xmit(%x,%x) called\n", dev->name, skb->len, (unsigned int)skb->data)); netif_stop_queue(dev); @@ -1044,8 +1078,8 @@ tbd = lp->tbds + lp->next_tx_cmd; if (tx_cmd->cmd.command) { - DEB(DEB_ERRORS,printk ("%s: xmit ring full, dropping packet.\n", - dev->name)); + printk(KERN_NOTICE "%s: xmit ring full, dropping packet.\n", + dev->name); lp->stats.tx_dropped++; dev_kfree_skb(skb); @@ -1084,7 +1118,7 @@ { int i; - printk("i596 0x%p, ", add); + printk(KERN_DEBUG "i596 0x%p, ", add); for (i = 0; i < 6; i++) printk(" %02X", add[i + 6]); printk(" -->"); @@ -1106,7 +1140,7 @@ #ifdef ENABLE_MVME16x_NET if (MACH_IS_MVME16x) { if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) { - printk("Ethernet probe disabled - chip not present\n"); + printk(KERN_NOTICE "Ethernet probe disabled - chip not present\n"); return -ENODEV; } memcpy(eth_addr, (void *) 0xfffc1f2c, 6); /* YUCK! Get addr from NOVRAM */ @@ -1137,7 +1171,7 @@ /* first check nothing is already registered here */ if (!request_region(ioaddr, I596_TOTAL_SIZE, dev->name)) { - printk("82596: IO address 0x%04x in use\n", ioaddr); + printk(KERN_ERR "82596: IO address 0x%04x in use\n", ioaddr); return -EBUSY; } @@ -1171,14 +1205,14 @@ } ether_setup(dev); - DEB(DEB_PROBE,printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr)); + DEB(DEB_PROBE,printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr)); for (i = 0; i < 6; i++) DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i])); DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq)); - DEB(DEB_PROBE,printk(version)); + DEB(DEB_PROBE,printk(KERN_INFO "%s", version)); /* The 82596-specific entries in the device structure. */ dev->open = i596_open; @@ -1192,7 +1226,7 @@ dev->priv = (void *)(dev->mem_start); lp = (struct i596_private *) dev->priv; - DEB(DEB_INIT,printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n", + DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n", dev->name, (unsigned long)lp, sizeof(struct i596_private), (unsigned long)&lp->scb)); memset((void *) lp, 0, sizeof(struct i596_private)); @@ -1220,13 +1254,13 @@ #ifdef ENABLE_BVME6000_NET if (MACH_IS_BVME6000) { if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) { - i596_error(BVME_IRQ_I596, NULL, NULL); + i596_error(irq, dev_id, regs); return; } } #endif if (dev == NULL) { - printk("i596_interrupt(): irq %d for unknown device.\n", irq); + printk(KERN_ERR "i596_interrupt(): irq %d for unknown device.\n", irq); return; } @@ -1238,7 +1272,7 @@ wait_cmd(dev,lp,100,"i596 interrupt, timeout"); status = lp->scb.status; - DEB(DEB_INTS,printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n", + DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt, IRQ %d, status %4.4x.\n", dev->name, irq, status)); ack_cmd = status & 0xf000; @@ -1247,14 +1281,14 @@ struct i596_cmd *ptr; if ((status & 0x8000)) - DEB(DEB_INTS,printk("%s: i596 interrupt completed command.\n", dev->name)); + DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt completed command.\n", dev->name)); if ((status & 0x2000)) - DEB(DEB_INTS,printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); + DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); while ((lp->cmd_head != I596_NULL) && (lp->cmd_head->status & STAT_C)) { ptr = lp->cmd_head; - DEB(DEB_STATUS,printk("cmd_head->status = %04x, ->command = %04x\n", + DEB(DEB_STATUS,printk(KERN_DEBUG "cmd_head->status = %04x, ->command = %04x\n", lp->cmd_head->status, lp->cmd_head->command)); lp->cmd_head = ptr->v_next; lp->cmd_backlog--; @@ -1291,20 +1325,21 @@ unsigned short status = ((struct tdr_cmd *)ptr)->status; if (status & 0x8000) { - DEB(DEB_ANY,printk("%s: link ok.\n", dev->name)); + DEB(DEB_TDR,printk(KERN_INFO "%s: link ok.\n", dev->name)); } else { if (status & 0x4000) - printk("%s: Transceiver problem.\n", dev->name); + printk(KERN_ERR "%s: Transceiver problem.\n", dev->name); if (status & 0x2000) - printk("%s: Termination problem.\n", dev->name); + printk(KERN_ERR "%s: Termination problem.\n", dev->name); if (status & 0x1000) - printk("%s: Short circuit.\n", dev->name); + printk(KERN_ERR "%s: Short circuit.\n", dev->name); - DEB(DEB_TDR,printk("%s: Time %d.\n", dev->name, status & 0x07ff)); + DEB(DEB_TDR,printk(KERN_INFO "%s: Time %d.\n", dev->name, status & 0x07ff)); } break; } case CmdConfigure: + case CmdMulticastList: /* Zap command so set_multicast_list() knows it is free */ ptr->command = 0; break; @@ -1325,12 +1360,12 @@ } if ((status & 0x1000) || (status & 0x4000)) { if ((status & 0x4000)) - DEB(DEB_INTS,printk("%s: i596 interrupt received a frame.\n", dev->name)); + DEB(DEB_INTS,printk(KERN_DEBUG "%s: i596 interrupt received a frame.\n", dev->name)); i596_rx(dev); /* Only RX_START if stopped - RGH 07-07-96 */ if (status & 0x1000) { if (netif_running(dev)) { - DEB(DEB_ERRORS,printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status)); + DEB(DEB_ERRORS,printk(KERN_ERR "%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status)); ack_cmd |= RX_START; lp->stats.rx_errors++; lp->stats.rx_fifo_errors++; @@ -1364,7 +1399,7 @@ #endif CA(dev); - DEB(DEB_INTS,printk("%s: exiting interrupt.\n", dev->name)); + DEB(DEB_INTS,printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name)); spin_unlock (&lp->lock); return; @@ -1377,7 +1412,7 @@ netif_stop_queue(dev); - DEB(DEB_INIT,printk("%s: Shutting down ethercard, status was %4.4x.\n", + DEB(DEB_INIT,printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n", dev->name, lp->scb.status)); save_flags(flags); @@ -1434,7 +1469,13 @@ struct i596_private *lp = (struct i596_private *) dev->priv; int config = 0, cnt; - DEB(DEB_MULTI,printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); + DEB(DEB_MULTI,printk(KERN_DEBUG "%s: set multicast list, %d entries, promisc %s, allmulti %s\n", + dev->name, dev->mc_count, + dev->flags & IFF_PROMISC ? "ON" : "OFF", + dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); + + if (wait_cfg(dev, &lp->cf_cmd.cmd, 1000, "config change request timed out")) + return; if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) { lp->cf_cmd.i596_config[8] |= 0x01; @@ -1453,20 +1494,15 @@ config = 1; } if (config) { - if (lp->cf_cmd.cmd.command) - printk("%s: config change request already queued\n", - dev->name); - else { - lp->cf_cmd.cmd.command = CmdConfigure; - i596_add_cmd(dev, &lp->cf_cmd.cmd); - } + lp->cf_cmd.cmd.command = CmdConfigure; + i596_add_cmd(dev, &lp->cf_cmd.cmd); } cnt = dev->mc_count; if (cnt > MAX_MC_CNT) { cnt = MAX_MC_CNT; - printk("%s: Only %d multicast addresses supported", + printk(KERN_ERR "%s: Only %d multicast addresses supported", dev->name, cnt); } @@ -1475,6 +1511,8 @@ unsigned char *cp; struct mc_cmd *cmd; + if (wait_cfg(dev, &lp->mc_cmd.cmd, 1000, "multicast list change request timed out")) + return; cmd = &lp->mc_cmd; cmd->cmd.command = CmdMulticastList; cmd->mc_cnt = dev->mc_count * 6; @@ -1482,7 +1520,7 @@ for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { memcpy(cp, dmi->dmi_addr, 6); if (i596_debug > 1) - DEB(DEB_MULTI,printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", + DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); } i596_add_cmd(dev, &cmd->cmd); diff -Nru a/drivers/net/8390.h b/drivers/net/8390.h --- a/drivers/net/8390.h Wed Jul 24 14:03:39 2002 +++ b/drivers/net/8390.h Wed Jul 24 14:03:39 2002 @@ -106,13 +106,24 @@ /* * Only generate indirect loads given a machine that needs them. + * - removed AMIGA_PCMCIA from this list, handled as ISA io now */ -#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \ +#if defined(CONFIG_MAC) || \ defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) || \ defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE) || \ defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) +#undef inb +#undef inb_p +#undef outb +#undef outb_p + +#define inb(port) in_8(port) +#define outb(val,port) out_8(port,val) +#define inb_p(port) in_8(port) +#define outb_p(val,port) out_8(port,val) + #else #define EI_SHIFT(x) (x) #endif diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c Wed Jul 24 14:03:36 2002 +++ b/drivers/net/Space.c Wed Jul 24 14:03:36 2002 @@ -99,7 +99,7 @@ extern int mvme147lance_probe(struct net_device *dev); extern int tc515_probe(struct net_device *dev); extern int lance_probe(struct net_device *dev); -extern int mace68k_probe(struct net_device *dev); +extern int mace_probe(struct net_device *dev); extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); @@ -354,7 +354,7 @@ {mvme147lance_probe, 0}, #endif #ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */ - {mace68k_probe, 0}, + {mace_probe, 0}, #endif #ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */ {macsonic_probe, 0}, diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c --- a/drivers/net/a2065.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/a2065.c Wed Jul 24 14:03:38 2002 @@ -639,7 +639,7 @@ volatile u16 *mcast_table = (u16 *)&ib->filter; struct dev_mc_list *dmi=dev->mc_list; char *addrs; - int i, j, bit, byte; + int i; u32 crc; /* set all multicast bits */ diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/acenic.c Wed Jul 24 14:03:38 2002 @@ -3389,14 +3389,13 @@ * Don't take interrupts on this CPU will bit banging * the %#%#@$ I2C device */ - __save_flags(flags); - __cli(); + local_irq_save(flags); eeprom_start(regs); eeprom_prep(regs, EEPROM_WRITE_SELECT); if (eeprom_check_ack(regs)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_ERR "%s: Unable to sync eeprom\n", dev->name); result = -EIO; goto eeprom_read_error; @@ -3404,7 +3403,7 @@ eeprom_prep(regs, (offset >> 8) & 0xff); if (eeprom_check_ack(regs)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set address byte 0\n", dev->name); result = -EIO; @@ -3413,7 +3412,7 @@ eeprom_prep(regs, offset & 0xff); if (eeprom_check_ack(regs)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set address byte 1\n", dev->name); result = -EIO; @@ -3423,7 +3422,7 @@ eeprom_start(regs); eeprom_prep(regs, EEPROM_READ_SELECT); if (eeprom_check_ack(regs)) { - __restore_flags(flags); + local_irq_restore(flags); printk(KERN_ERR "%s: Unable to set READ_SELECT\n", dev->name); result = -EIO; @@ -3469,7 +3468,7 @@ udelay(ACE_SHORT_DELAY); eeprom_stop(regs); - __restore_flags(flags); + local_irq_restore(flags); out: return result; diff -Nru a/drivers/net/atarilance.c b/drivers/net/atarilance.c --- a/drivers/net/atarilance.c Wed Jul 24 14:03:36 2002 +++ b/drivers/net/atarilance.c Wed Jul 24 14:03:36 2002 @@ -565,7 +565,7 @@ } if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO, "Riebl-VME Ethernet", dev)) { - printk( "Lance: request for irq %d failed\n", irq ); + printk( "Lance: request for irq %ld failed\n", irq ); return( 0 ); } dev->irq = irq; @@ -926,7 +926,7 @@ #ifndef final_version if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { DPRINTK( 0, ( "out-of-sync dirty pointer," - " %d vs. %d, full=%d.\n", + " %d vs. %d, full=%ld.\n", dirty_tx, lp->cur_tx, lp->tx_full )); dirty_tx += TX_RING_SIZE; } diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c --- a/drivers/net/eepro100.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/eepro100.c Wed Jul 24 14:03:38 2002 @@ -1354,7 +1354,7 @@ udelay(10); /* Disable interrupts. */ outw(SCBMaskAll, ioaddr + SCBCmd); - synchronize_irq(); + synchronize_irq(dev->irq); speedo_tx_buffer_gc(dev); /* Free as much as possible. It helps to recover from a hang because of out-of-memory. diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Wed Jul 24 14:03:36 2002 +++ b/drivers/net/fc/iph5526.c Wed Jul 24 14:03:36 2002 @@ -3891,7 +3891,7 @@ } -int iph5526_biosparam(Disk * disk, kdev_t n, int ip[]) +int iph5526_biosparam(Disk * disk, struct block_device *n, int ip[]) { int size = disk->capacity; ip[0] = 64; diff -Nru a/drivers/net/fc/iph5526_scsi.h b/drivers/net/fc/iph5526_scsi.h --- a/drivers/net/fc/iph5526_scsi.h Wed Jul 24 14:03:35 2002 +++ b/drivers/net/fc/iph5526_scsi.h Wed Jul 24 14:03:35 2002 @@ -25,7 +25,7 @@ int iph5526_release(struct Scsi_Host *host); int iph5526_abort(Scsi_Cmnd *Cmnd); const char *iph5526_info(struct Scsi_Host *host); -int iph5526_biosparam(Disk * disk, kdev_t n, int ip[]); +int iph5526_biosparam(Disk * disk, struct block_device *n, int ip[]); #endif diff -Nru a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c --- a/drivers/net/hamradio/baycom_par.c Wed Jul 24 14:03:39 2002 +++ b/drivers/net/hamradio/baycom_par.c Wed Jul 24 14:03:39 2002 @@ -288,14 +288,14 @@ par96_rx(dev, bc); if (--bc->modem.arb_divider <= 0) { bc->modem.arb_divider = 6; - __sti(); + local_irq_enable(); hdlcdrv_arbitrate(dev, &bc->hdrv); } } - __sti(); + local_irq_enable(); hdlcdrv_transmitter(dev, &bc->hdrv); hdlcdrv_receiver(dev, &bc->hdrv); - __cli(); + local_irq_disable(); } /* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c --- a/drivers/net/hamradio/baycom_ser_fdx.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/hamradio/baycom_ser_fdx.c Wed Jul 24 14:03:38 2002 @@ -350,7 +350,7 @@ bc->modem.ser12.txshreg >>= 1; } end_transmit: - __sti(); + local_irq_enable(); if (!bc->modem.ptt && txcount) { hdlcdrv_arbitrate(dev, &bc->hdrv); if (hdlcdrv_ptt(&bc->hdrv)) { @@ -361,7 +361,7 @@ } hdlcdrv_transmitter(dev, &bc->hdrv); hdlcdrv_receiver(dev, &bc->hdrv); - __cli(); + local_irq_disable(); } /* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c --- a/drivers/net/hamradio/baycom_ser_hdx.c Wed Jul 24 14:03:35 2002 +++ b/drivers/net/hamradio/baycom_ser_hdx.c Wed Jul 24 14:03:35 2002 @@ -416,13 +416,13 @@ } while (!(iir & 1)); if (bc->modem.arb_divider <= 0) { bc->modem.arb_divider = SER12_ARB_DIVIDER(bc); - __sti(); + local_irq_enable(); hdlcdrv_arbitrate(dev, &bc->hdrv); } - __sti(); + local_irq_enable(); hdlcdrv_transmitter(dev, &bc->hdrv); hdlcdrv_receiver(dev, &bc->hdrv); - __cli(); + local_irq_disable(); } /* --------------------------------------------------------------------- */ diff -Nru a/drivers/net/hplance.c b/drivers/net/hplance.c --- a/drivers/net/hplance.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/hplance.c Wed Jul 24 14:03:38 2002 @@ -58,9 +58,9 @@ static int hplance_init(struct net_device *dev, int scode); static int hplance_open(struct net_device *dev); static int hplance_close(struct net_device *dev); -static void hplance_writerap(struct hplance_private *lp, unsigned short value); -static void hplance_writerdp(struct hplance_private *lp, unsigned short value); -static unsigned short hplance_readrdp(struct hplance_private *lp); +static void hplance_writerap(void *priv, unsigned short value); +static void hplance_writerdp(void *priv, unsigned short value); +static unsigned short hplance_readrdp(void *priv); #ifdef MODULE static struct hplance_private *root_hplance_dev; @@ -100,8 +100,7 @@ /* Initialise a single lance board at the given select code */ static int __init hplance_init(struct net_device *dev, int scode) { - /* const char *name = dio_scodetoname(scode); */ - static const char name[] = "HP LANCE"; + const char *name = dio_scodetoname(scode); void *va = dio_scodetoviraddr(scode); struct hplance_private *lp; int i; @@ -118,10 +117,10 @@ #endif SET_MODULE_OWNER(dev); - printk("%s: HP LANCE; select code %d, addr", dev->name, scode); + printk("%s: %s; select code %d, addr", dev->name, name, scode); /* reset the board */ - writeb(0xff,va+DIO_IDOFF); + out_8(va+DIO_IDOFF, 0xff); udelay(100); /* ariba! ariba! udelay! udelay! */ /* Fill the dev fields */ @@ -138,8 +137,8 @@ /* The NVRAM holds our ethernet address, one nibble per byte, * at bytes NVRAMOFF+1,3,5,7,9... */ - dev->dev_addr[i] = ((readb(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4) - | (readb(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF); + dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4) + | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF); printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]); } @@ -175,25 +174,28 @@ /* This is disgusting. We have to check the DIO status register for ack every * time we read or write the LANCE registers. */ -static void hplance_writerap(struct hplance_private *lp, unsigned short value) +static void hplance_writerap(void *priv, unsigned short value) { + struct hplance_private *lp = (struct hplance_private *)priv; struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; do { lp->lance.ll->rap = value; } while ((hpregs->status & LE_ACK) == 0); } -static void hplance_writerdp(struct hplance_private *lp, unsigned short value) +static void hplance_writerdp(void *priv, unsigned short value) { + struct hplance_private *lp = (struct hplance_private *)priv; struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; do { lp->lance.ll->rdp = value; } while ((hpregs->status & LE_ACK) == 0); } -static unsigned short hplance_readrdp(struct hplance_private *lp) +static unsigned short hplance_readrdp(void *priv) { unsigned short val; + struct hplance_private *lp = (struct hplance_private *)priv; struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; do { val = lp->lance.ll->rdp; @@ -211,7 +213,7 @@ if (status) return status; /* enable interrupts at board level. */ - writeb(LE_IE, &(hpregs->status)); + out_8(&(hpregs->status), LE_IE); return 0; } @@ -220,7 +222,7 @@ { struct hplance_private *lp = (struct hplance_private *)dev->priv; struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; - writeb(0,&(hpregs->status)); /* disable interrupts at boardlevel */ + out_8(&(hpregs->status), 8); /* disable interrupts at boardlevel */ lance_close(dev); return 0; } diff -Nru a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c --- a/drivers/net/mac89x0.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/mac89x0.c Wed Jul 24 14:03:38 2002 @@ -144,28 +144,28 @@ static int inline readreg_io(struct net_device *dev, int portno) { - writew(swab16(portno), dev->base_addr + ADD_PORT); - return swab16(readw(dev->base_addr + DATA_PORT)); + nubus_writew(swab16(portno), dev->base_addr + ADD_PORT); + return swab16(nubus_readw(dev->base_addr + DATA_PORT)); } static void inline writereg_io(struct net_device *dev, int portno, int value) { - writew(swab16(portno), dev->base_addr + ADD_PORT); - writew(swab16(value), dev->base_addr + DATA_PORT); + nubus_writew(swab16(portno), dev->base_addr + ADD_PORT); + nubus_writew(swab16(value), dev->base_addr + DATA_PORT); } /* These are for reading/writing registers in shared memory */ static int inline readreg(struct net_device *dev, int portno) { - return swab16(readw(dev->mem_start + portno)); + return swab16(nubus_readw(dev->mem_start + portno)); } static void inline writereg(struct net_device *dev, int portno, int value) { - writew(swab16(value), dev->mem_start + portno); + nubus_writew(swab16(value), dev->mem_start + portno); } /* Probe for the CS8900 card in slot E. We won't bother looking @@ -210,8 +210,8 @@ return -ENODEV; } - writew(0, ioaddr + ADD_PORT); - sig = readw(ioaddr + DATA_PORT); + nubus_writew(0, ioaddr + ADD_PORT); + sig = nubus_readw(ioaddr + DATA_PORT); if (sig != swab16(CHIP_EISA_ID_SIG)) return -ENODEV; @@ -450,7 +450,7 @@ course, if you're on a slow machine, and packets are arriving faster than you can read them off, you're screwed. Hasta la vista, baby! */ - while ((status = swab16(readw(dev->base_addr + ISQ_PORT)))) { + while ((status = swab16(nubus_readw(dev->base_addr + ISQ_PORT)))) { if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status); switch(status & ISQ_EVENT_MASK) { case ISQ_RECEIVER_EVENT: @@ -653,7 +653,7 @@ #endif #ifdef MODULE - writew(0, dev_cs89x0.base_addr + ADD_PORT); + nubus_writew(0, dev_cs89x0.base_addr + ADD_PORT); #endif #ifdef MODULE diff -Nru a/drivers/net/macmace.c b/drivers/net/macmace.c --- a/drivers/net/macmace.c Wed Jul 24 14:03:37 2002 +++ b/drivers/net/macmace.c Wed Jul 24 14:03:37 2002 @@ -10,15 +10,17 @@ * * Copyright (C) 1996 Paul Mackerras. * Copyright (C) 1998 Alan Cox + * + * Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver */ #include +#include #include #include #include #include -#include #include #include #include @@ -26,14 +28,13 @@ #include #include #include +#include #include "mace.h" +#define N_TX_RING 1 #define N_RX_RING 8 -#define N_TX_RING 2 -#define MAX_TX_ACTIVE 1 -#define NCMDS_TX 1 /* dma commands per element in tx ring */ -#define RX_BUFLEN (ETH_FRAME_LEN + 8) -#define TX_TIMEOUT HZ /* 1 second */ +#define N_RX_PAGES ((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE) +#define TX_TIMEOUT HZ /* Bits in transmit DMA status */ #define TX_DMA_ERR 0x80 @@ -43,22 +44,19 @@ #define MACE_BASE (void *)(0x50F1C000) #define MACE_PROM (void *)(0x50F08001) -struct mace68k_data -{ +struct mace_data { volatile struct mace *mace; volatile unsigned char *tx_ring; + volatile unsigned char *tx_ring_phys; volatile unsigned char *rx_ring; + volatile unsigned char *rx_ring_phys; int dma_intr; - unsigned char maccc; struct net_device_stats stats; - struct timer_list tx_timeout; - int timeout_active; - int rx_slot, rx_done; - int tx_slot, tx_count; + int rx_slot, rx_tail; + int tx_slot, tx_sloti, tx_count; }; -struct mace_frame -{ +struct mace_frame { u16 len; u16 status; u16 rntpc; @@ -69,271 +67,226 @@ /* And frame continues.. */ }; -#define PRIV_BYTES sizeof(struct mace68k_data) +#define PRIV_BYTES sizeof(struct mace_data) extern void psc_debug_dump(void); -static int mace68k_open(struct net_device *dev); -static int mace68k_close(struct net_device *dev); -static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev); -static struct net_device_stats *mace68k_stats(struct net_device *dev); -static void mace68k_set_multicast(struct net_device *dev); -static void mace68k_reset(struct net_device *dev); -static int mace68k_set_address(struct net_device *dev, void *addr); -static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs); -static void mace68k_set_timeout(struct net_device *dev); -static void mace68k_tx_timeout(unsigned long data); +static int mace_open(struct net_device *dev); +static int mace_close(struct net_device *dev); +static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *mace_stats(struct net_device *dev); +static void mace_set_multicast(struct net_device *dev); +static int mace_set_address(struct net_device *dev, void *addr); +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs); +static void mace_tx_timeout(struct net_device *dev); -/* - * PSC DMA engine control. As you'd expect on a macintosh its - * more like a lawnmower engine supplied without instructions - * - * The basic theory of operation appears to be as follows. - * - * There are two sets of receive DMA registers and two sets - * of transmit DMA registers. Instead of the more traditional - * "ring buffer" approach the Mac68K DMA engine expects you - * to be loading one chain while the other runs, and then - * to flip register set. Each entry in the chain is a fixed - * length. - */ +/* Bit-reverse one byte of an ethernet hardware address. */ + +static int bitrev(int b) +{ + int d = 0, i; + + for (i = 0; i < 8; ++i, b >>= 1) { + d = (d << 1) | (b & 1); + } + + return d; +} /* - * Load a receive DMA channel with a base address and ring length + * Load a receive DMA channel with a base address and ring length */ - -static void psc_load_rxdma_base(int set, void *base) + +static void mace_load_rxdma_base(struct net_device *dev, int set) { + struct mace_data *mp = (struct mace_data *) dev->priv; + psc_write_word(PSC_ENETRD_CMD + set, 0x0100); - psc_write_long(PSC_ENETRD_ADDR + set, (u32)base); + psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys); psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING); psc_write_word(PSC_ENETRD_CMD + set, 0x9800); + mp->rx_tail = 0; } /* - * Reset the receive DMA subsystem + * Reset the receive DMA subsystem */ - -static void mace68k_rxdma_reset(struct net_device *dev) + +static void mace_rxdma_reset(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mace = mp->mace; - u8 mcc = mace->maccc; - - /* - * Turn off receive - */ - - mcc&=~ENRCV; - mace->maccc=mcc; + u8 maccc = mace->maccc; - /* - * Program the DMA - */ + mace->maccc = maccc & ~ENRCV; psc_write_word(PSC_ENETRD_CTL, 0x8800); - psc_load_rxdma_base(0x0, (void *)virt_to_bus(mp->rx_ring)); + mace_load_rxdma_base(dev, 0x00); psc_write_word(PSC_ENETRD_CTL, 0x0400); psc_write_word(PSC_ENETRD_CTL, 0x8800); - psc_load_rxdma_base(0x10, (void *)virt_to_bus(mp->rx_ring)); + mace_load_rxdma_base(dev, 0x10); psc_write_word(PSC_ENETRD_CTL, 0x0400); - mace->maccc=mcc|ENRCV; - -#if 0 - psc_write_word(PSC_ENETRD_CTL, 0x9800); - psc_write_word(PSC_ENETRD_CTL+0x10, 0x9800); -#endif + mace->maccc = maccc; + mp->rx_slot = 0; + + psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x9800); + psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x9800); } /* - * Reset the transmit DMA subsystem + * Reset the transmit DMA subsystem */ -static void mace68k_txdma_reset(struct net_device *dev) +static void mace_txdma_reset(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mace = mp->mace; - u8 mcc = mace->maccc; + u8 maccc; - psc_write_word(PSC_ENETWR_CTL,0x8800); - - mace->maccc = mcc&~ENXMT; - psc_write_word(PSC_ENETWR_CTL,0x0400); - mace->maccc = mcc; + psc_write_word(PSC_ENETWR_CTL, 0x8800); + + maccc = mace->maccc; + mace->maccc = maccc & ~ENXMT; + + mp->tx_slot = mp->tx_sloti = 0; + mp->tx_count = N_TX_RING; + + psc_write_word(PSC_ENETWR_CTL, 0x0400); + mace->maccc = maccc; } /* - * Disable DMA + * Disable DMA */ -static void mace68k_dma_off(struct net_device *dev) +static void mace_dma_off(struct net_device *dev) { psc_write_word(PSC_ENETRD_CTL, 0x8800); psc_write_word(PSC_ENETRD_CTL, 0x1000); - psc_write_word(PSC_ENETRD_CMD, 0x1100); - psc_write_word(PSC_ENETRD_CMD+0x10, 0x1100); - + psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x1100); + psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x1100); + psc_write_word(PSC_ENETWR_CTL, 0x8800); psc_write_word(PSC_ENETWR_CTL, 0x1000); - psc_write_word(PSC_ENETWR_CMD, 0x1100); - psc_write_word(PSC_ENETWR_CMD+0x10, 0x1100); -} - -/* Bit-reverse one byte of an ethernet hardware address. */ - -static int bitrev(int b) -{ - int d = 0, i; - - for (i = 0; i < 8; ++i, b >>= 1) - d = (d << 1) | (b & 1); - return d; + psc_write_word(PSC_ENETWR_CMD + PSC_SET0, 0x1100); + psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100); } /* - * Not really much of a probe. The hardware table tells us if this - * model of Macintrash has a MACE (AV macintoshes) + * Not really much of a probe. The hardware table tells us if this + * model of Macintrash has a MACE (AV macintoshes) */ -int mace68k_probe(struct net_device *unused) +int mace_probe(struct net_device *unused) { int j; - static int once; - struct mace68k_data *mp; + struct mace_data *mp; unsigned char *addr; struct net_device *dev; unsigned char checksum = 0; + static int found = 0; - /* - * There can be only one... - */ - - if (once) return -ENODEV; - - once = 1; + if (found || macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV; - if (macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV; + found = 1; /* prevent 'finding' one on every device probe */ - printk("MACE ethernet should be present "); - dev = init_etherdev(0, PRIV_BYTES); - if(dev==NULL) - { - printk("no free memory.\n"); - return -ENOMEM; - } - mp = (struct mace68k_data *) dev->priv; + if (!dev) return -ENOMEM; + + mp = (struct mace_data *) dev->priv; dev->base_addr = (u32)MACE_BASE; mp->mace = (volatile struct mace *) MACE_BASE; - printk("at 0x%p", mp->mace); - - /* - * 16K RX ring and 4K TX ring should do nicely - */ - - mp->rx_ring=(void *)__get_free_pages(GFP_KERNEL, 2); - mp->tx_ring=(void *)__get_free_page(GFP_KERNEL); - - printk("."); - - if(mp->tx_ring==NULL || mp->rx_ring==NULL) - { - if(mp->tx_ring) - free_page((u32)mp->tx_ring); -// if(mp->rx_ring) -// __free_pages(mp->rx_ring,2); - printk("\nNo memory for ring buffers.\n"); - return -ENOMEM; - } - - /* We want the receive data to be uncached. We dont care about the - byte reading order */ - - printk("."); - kernel_set_cachemode((void *)mp->rx_ring, 16384, IOMAP_NOCACHE_NONSER); - - printk("."); - /* The transmit buffer needs to be write through */ - kernel_set_cachemode((void *)mp->tx_ring, 4096, IOMAP_WRITETHROUGH); - - printk(" Ok\n"); dev->irq = IRQ_MAC_MACE; - printk(KERN_INFO "%s: MACE at", dev->name); + mp->dma_intr = IRQ_MAC_MACE_DMA; /* - * The PROM contains 8 bytes which total 0xFF when XOR'd - * together. Due to the usual peculiar apple brain damage - * the bytes are spaced out in a strange boundary and the - * bits are reversed. + * The PROM contains 8 bytes which total 0xFF when XOR'd + * together. Due to the usual peculiar apple brain damage + * the bytes are spaced out in a strange boundary and the + * bits are reversed. */ addr = (void *)MACE_PROM; - for (j = 0; j < 6; ++j) - { + for (j = 0; j < 6; ++j) { u8 v=bitrev(addr[j<<4]); - checksum^=v; + checksum ^= v; dev->dev_addr[j] = v; - printk("%c%.2x", (j ? ':' : ' '), dev->dev_addr[j]); } - for (; j < 8; ++j) - { - checksum^=bitrev(addr[j<<4]); + for (; j < 8; ++j) { + checksum ^= bitrev(addr[j<<4]); } - if(checksum!=0xFF) - { - printk(" (invalid checksum)\n"); - return -ENODEV; - } - printk("\n"); + if (checksum != 0xFF) return -ENODEV; memset(&mp->stats, 0, sizeof(mp->stats)); - init_timer(&mp->tx_timeout); - mp->timeout_active = 0; - dev->open = mace68k_open; - dev->stop = mace68k_close; - dev->hard_start_xmit = mace68k_xmit_start; - dev->get_stats = mace68k_stats; - dev->set_multicast_list = mace68k_set_multicast; - dev->set_mac_address = mace68k_set_address; + dev->open = mace_open; + dev->stop = mace_close; + dev->hard_start_xmit = mace_xmit_start; + dev->tx_timeout = mace_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + dev->get_stats = mace_stats; + dev->set_multicast_list = mace_set_multicast; + dev->set_mac_address = mace_set_address; ether_setup(dev); - mp = (struct mace68k_data *) dev->priv; - mp->maccc = ENXMT | ENRCV; - mp->dma_intr = IRQ_MAC_MACE_DMA; + printk(KERN_INFO "%s: 68K MACE, hardware address %.2X", dev->name, dev->dev_addr[0]); + for (j = 1 ; j < 6 ; j++) printk(":%.2X", dev->dev_addr[j]); + printk("\n"); - psc_write_word(PSC_ENETWR_CTL, 0x9000); - psc_write_word(PSC_ENETRD_CTL, 0x9000); - psc_write_word(PSC_ENETWR_CTL, 0x0400); - psc_write_word(PSC_ENETRD_CTL, 0x0400); - - /* apple's driver doesn't seem to do this */ - /* except at driver shutdown time... */ -#if 0 - mace68k_dma_off(dev); -#endif + return 0; +} + +/* + * Load the address on a mace controller. + */ + +static int mace_set_address(struct net_device *dev, void *addr) +{ + unsigned char *p = addr; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + int i; + unsigned long flags; + u8 maccc; + + save_flags(flags); + cli(); + + maccc = mb->maccc; + + /* load up the hardware address */ + mb->iac = ADDRCHG | PHYADDR; + while ((mb->iac & ADDRCHG) != 0); + + for (i = 0; i < 6; ++i) { + mb->padr = dev->dev_addr[i] = p[i]; + } + + mb->maccc = maccc; + restore_flags(flags); return 0; } /* - * Reset a MACE controller + * Open the Macintosh MACE. Most of this is playing with the DMA + * engine. The ethernet chip is quite friendly. */ -static void mace68k_reset(struct net_device *dev) +static int mace_open(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; +#if 0 int i; - /* soft-reset the chip */ i = 200; while (--i) { mb->biucc = SWRST; @@ -344,18 +297,59 @@ break; } if (!i) { - printk(KERN_ERR "mace: cannot reset chip!\n"); - return; + printk(KERN_ERR "%s: software reset failed!!\n", dev->name); + return -EAGAIN; } +#endif mb->biucc = XMTSP_64; - mb->imr = 0xff; /* disable all intrs for now */ - i = mb->ir; - mb->maccc = 0; /* turn off tx, rx */ - mb->utr = RTRD; - mb->fifocc = RCVFW_64; - mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */ + mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST; + mb->xmtfc = AUTO_PAD_XMIT; + mb->plscc = PORTSEL_AUI; + /* mb->utr = RTRD; */ + + if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) { + printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq); + return -EAGAIN; + } + if (request_irq(mp->dma_intr, mace_dma_intr, 0, dev->name, dev)) { + printk(KERN_ERR "%s: can't get irq %d\n", dev->name, mp->dma_intr); + free_irq(dev->irq, dev); + return -EAGAIN; + } + + /* Allocate the DMA ring buffers */ + + mp->rx_ring = (void *) __get_free_pages(GFP_DMA, N_RX_PAGES); + mp->tx_ring = (void *) __get_free_pages(GFP_DMA, 0); + + if (mp->tx_ring==NULL || mp->rx_ring==NULL) { + if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES); + if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0); + free_irq(dev->irq, dev); + free_irq(mp->dma_intr, dev); + printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name); + return -ENOMEM; + } + + mp->rx_ring_phys = (unsigned char *) virt_to_bus(mp->rx_ring); + mp->tx_ring_phys = (unsigned char *) virt_to_bus(mp->tx_ring); + + /* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */ + + kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER); + kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH); + + mace_dma_off(dev); + + /* Not sure what these do */ + psc_write_word(PSC_ENETWR_CTL, 0x9000); + psc_write_word(PSC_ENETRD_CTL, 0x9000); + psc_write_word(PSC_ENETWR_CTL, 0x0400); + psc_write_word(PSC_ENETRD_CTL, 0x0400); + +#if 0 /* load up the hardware address */ mb->iac = ADDRCHG | PHYADDR; @@ -374,245 +368,157 @@ mb->ladrf = 0; mb->plscc = PORTSEL_GPSI + ENPLSIO; -} - -/* - * Load the address on a mace controller. - */ - -static int mace68k_set_address(struct net_device *dev, void *addr) -{ - unsigned char *p = addr; - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; - volatile struct mace *mb = mp->mace; - int i; - unsigned long flags; - save_flags(flags); - cli(); + mb->maccc = ENXMT | ENRCV; + mb->imr = RCVINT; +#endif - /* load up the hardware address */ - mb->iac = ADDRCHG | PHYADDR; - while ((mb->iac & ADDRCHG) != 0); + mace_rxdma_reset(dev); + mace_txdma_reset(dev); - for (i = 0; i < 6; ++i) - mb->padr = dev->dev_addr[i] = p[i]; - /* note: setting ADDRCHG clears ENRCV */ - mb->maccc = mp->maccc; - restore_flags(flags); return 0; } /* - * Open the Macintosh MACE. Most of this is playing with the DMA - * engine. The ethernet chip is quite friendly. + * Shut down the mace and its interrupt channel */ -static int mace68k_open(struct net_device *dev) +static int mace_close(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; - /* reset the chip */ - mace68k_reset(dev); - - mp->rx_done = 0; - mace68k_rxdma_reset(dev); - - /* - * The interrupt is fixed and comes off the PSC. - */ - - if (request_irq(dev->irq, mace68k_interrupt, 0, "68K MACE", dev)) - { - printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq); - return -EAGAIN; - } + mb->maccc = 0; /* disable rx and tx */ + mb->imr = 0xFF; /* disable all irqs */ + mace_dma_off(dev); /* disable rx and tx dma */ - /* - * Ditto the DMA interrupt. - */ - - if (request_irq(IRQ_MAC_MACE_DMA, mace68k_dma_intr, 0, "68K MACE DMA", - dev)) - { - printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA); - return -EAGAIN; - } + free_irq(dev->irq, dev); + free_irq(IRQ_MAC_MACE_DMA, dev); - /* Activate the Mac DMA engine */ + free_pages((u32) mp->rx_ring, N_RX_PAGES); + free_pages((u32) mp->tx_ring, 0); - mp->tx_slot = 0; /* Using register set 0 */ - mp->tx_count = 1; /* 1 Buffer ready for use */ - mace68k_txdma_reset(dev); - - /* turn it on! */ - mb->maccc = mp->maccc; - /* enable all interrupts except receive interrupts */ - mb->imr = RCVINT; return 0; } /* - * Shut down the mace and its interrupt channel + * Transmit a frame */ -static int mace68k_close(struct net_device *dev) +static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; - volatile struct mace *mb = mp->mace; + struct mace_data *mp = (struct mace_data *) dev->priv; - /* disable rx and tx */ - mb->maccc = 0; - mb->imr = 0xff; /* disable all intrs */ + /* Stop the queue if the buffer is full */ - /* disable rx and tx dma */ + if (!mp->tx_count) { + netif_stop_queue(dev); + return 1; + } + mp->tx_count--; + + mp->stats.tx_packets++; + mp->stats.tx_bytes += skb->len; - mace68k_dma_off(dev); + /* We need to copy into our xmit buffer to take care of alignment and caching issues */ - free_irq(dev->irq, dev); - free_irq(IRQ_MAC_MACE_DMA, dev); - return 0; -} + memcpy((void *) mp->tx_ring, skb->data, skb->len); -static inline void mace68k_set_timeout(struct net_device *dev) -{ - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; - unsigned long flags; + /* load the Tx DMA and fire it off */ - save_flags(flags); - cli(); - if (mp->timeout_active) - del_timer(&mp->tx_timeout); - mp->tx_timeout.expires = jiffies + TX_TIMEOUT; - mp->tx_timeout.function = mace68k_tx_timeout; - mp->tx_timeout.data = (unsigned long) dev; - add_timer(&mp->tx_timeout); - mp->timeout_active = 1; - restore_flags(flags); -} + psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, (u32) mp->tx_ring_phys); + psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len); + psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800); -/* - * Transmit a frame - */ - -static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev) -{ - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; - /* - * This may need atomic types ??? - */ + mp->tx_slot ^= 0x10; + + dev_kfree_skb(skb); - printk("mace68k_xmit_start: mp->tx_count = %d, dev->tbusy = %d, mp->tx_ring = %p (%p)\n", - mp->tx_count, dev->tbusy, - mp->tx_ring, virt_to_bus(mp->tx_ring)); - psc_debug_dump(); - - if(mp->tx_count == 0) - { - dev->tbusy=1; - mace68k_dma_intr(IRQ_MAC_MACE_DMA, dev, NULL); - return 1; - } - mp->tx_count--; - - /* - * FIXME: - * This is hackish. The memcpy probably isnt needed but - * the rules for alignment are not known. Ideally we'd like - * to just blast the skb directly to ethernet. We also don't - * use the ring properly - just a one frame buffer. That - * also requires cache pushes ;). - */ - memcpy((void *)mp->tx_ring, skb, skb->len); - psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, virt_to_bus(mp->tx_ring)); - psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len); - psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800); - mp->stats.tx_packets++; - mp->stats.tx_bytes+=skb->len; - dev_kfree_skb(skb); return 0; } -static struct net_device_stats *mace68k_stats(struct net_device *dev) +static struct net_device_stats *mace_stats(struct net_device *dev) { - struct mace68k_data *p = (struct mace68k_data *) dev->priv; + struct mace_data *p = (struct mace_data *) dev->priv; return &p->stats; } -static void mace68k_set_multicast(struct net_device *dev) +static void mace_set_multicast(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; - int i, j, k, b; + int i, j; u32 crc; + u8 maccc; + + maccc = mb->maccc; + mb->maccc &= ~PROM; - mp->maccc &= ~PROM; - if (dev->flags & IFF_PROMISC) - { - mp->maccc |= PROM; - } else - { + if (dev->flags & IFF_PROMISC) { + mb->maccc |= PROM; + } else { unsigned char multicast_filter[8]; struct dev_mc_list *dmi = dev->mc_list; - if (dev->flags & IFF_ALLMULTI) - { - for (i = 0; i < 8; i++) - multicast_filter[i] = 0xff; - } else - { + if (dev->flags & IFF_ALLMULTI) { + for (i = 0; i < 8; i++) { + multicast_filter[i] = 0xFF; + } + } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - for (i = 0; i < dev->mc_count; i++) - { + for (i = 0; i < dev->mc_count; i++) { crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); dmi = dmi->next; } } -#if 0 - printk("Multicast filter :"); - for (i = 0; i < 8; i++) - printk("%02x ", multicast_filter[i]); - printk("\n"); -#endif mb->iac = ADDRCHG | LOGADDR; - while ((mb->iac & ADDRCHG) != 0); + while (mb->iac & ADDRCHG); - for (i = 0; i < 8; ++i) + for (i = 0; i < 8; ++i) { mb->ladrf = multicast_filter[i]; + } } - /* reset maccc */ - mb->maccc = mp->maccc; + + mb->maccc = maccc; } /* - * Miscellaneous interrupts are handled here. We may end up - * having to bash the chip on the head for bad errors + * Miscellaneous interrupts are handled here. We may end up + * having to bash the chip on the head for bad errors */ -static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr) +static void mace_handle_misc_intrs(struct mace_data *mp, int intr) { volatile struct mace *mb = mp->mace; - static int mace68k_babbles, mace68k_jabbers; + static int mace_babbles, mace_jabbers; - if (intr & MPCO) + if (intr & MPCO) { mp->stats.rx_missed_errors += 256; + } mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ - if (intr & RNTPCO) + + if (intr & RNTPCO) { mp->stats.rx_length_errors += 256; + } mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ - if (intr & CERR) + + if (intr & CERR) { ++mp->stats.tx_heartbeat_errors; - if (intr & BABBLE) - if (mace68k_babbles++ < 4) + } + if (intr & BABBLE) { + if (mace_babbles++ < 4) { printk(KERN_DEBUG "mace: babbling transmitter\n"); - if (intr & JABBER) - if (mace68k_jabbers++ < 4) + } + } + if (intr & JABBER) { + if (mace_jabbers++ < 4) { printk(KERN_DEBUG "mace: jabbering transceiver\n"); + } + } } /* @@ -620,191 +526,172 @@ * the DMA completion) */ -static void mace68k_xmit_error(struct net_device *dev) +static void mace_xmit_error(struct net_device *dev) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; u8 xmtfs, xmtrc; xmtfs = mb->xmtfs; xmtrc = mb->xmtrc; - if(xmtfs & XMTSV) - { - if(xmtfs & UFLO) - { + if (xmtfs & XMTSV) { + if (xmtfs & UFLO) { printk("%s: DMA underrun.\n", dev->name); mp->stats.tx_errors++; mp->stats.tx_fifo_errors++; - mace68k_reset(dev); + mace_txdma_reset(dev); } - if(xmtfs & RTRY) + if (xmtfs & RTRY) { mp->stats.collisions++; + } } - mark_bh(NET_BH); } /* * A receive interrupt occurred. */ -static void mace68k_recv_interrupt(struct net_device *dev) +static void mace_recv_interrupt(struct net_device *dev) { -// struct mace68k_data *mp = (struct mace68k_data *) dev->priv; +/* struct mace_data *mp = (struct mace_data *) dev->priv; */ // volatile struct mace *mb = mp->mace; } /* - * Process the chip interrupt + * Process the chip interrupt */ -static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; u8 ir; ir = mb->ir; - mace68k_handle_misc_intrs(mp, ir); + mace_handle_misc_intrs(mp, ir); - if(ir&XMTINT) - mace68k_xmit_error(dev); - if(ir&RCVINT) - mace68k_recv_interrupt(dev); + if (ir & XMTINT) { + mace_xmit_error(dev); + } + if (ir & RCVINT) { + mace_recv_interrupt(dev); + } } -static void mace68k_tx_timeout(unsigned long data) +static void mace_tx_timeout(struct net_device *dev) { -// struct net_device *dev = (struct net_device *) data; -// struct mace68k_data *mp = (struct mace68k_data *) dev->priv; +/* struct mace_data *mp = (struct mace_data *) dev->priv; */ // volatile struct mace *mb = mp->mace; } /* - * Handle a newly arrived frame + * Handle a newly arrived frame */ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf) { - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; struct sk_buff *skb; - if(mf->status&RS_OFLO) - { + if (mf->status & RS_OFLO) { printk("%s: fifo overflow.\n", dev->name); mp->stats.rx_errors++; mp->stats.rx_fifo_errors++; } - if(mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR)) + if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR)) mp->stats.rx_errors++; - if(mf->status&RS_CLSN) + if (mf->status&RS_CLSN) { mp->stats.collisions++; - if(mf->status&RS_FRAMERR) + } + if (mf->status&RS_FRAMERR) { mp->stats.rx_frame_errors++; - if(mf->status&RS_FCSERR) + } + if (mf->status&RS_FCSERR) { mp->stats.rx_crc_errors++; + } skb = dev_alloc_skb(mf->len+2); - if(skb==NULL) - { + if (!skb) { mp->stats.rx_dropped++; return; } skb_reserve(skb,2); memcpy(skb_put(skb, mf->len), mf->data, mf->len); + skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; mp->stats.rx_packets++; - mp->stats.rx_bytes+=mf->len; + mp->stats.rx_bytes += mf->len; } /* - * The PSC has passed us a DMA interrupt event. + * The PSC has passed us a DMA interrupt event. */ -static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs) +static void mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; - struct mace68k_data *mp = (struct mace68k_data *) dev->priv; + struct mace_data *mp = (struct mace_data *) dev->priv; + int left, head; + u16 status; + u32 baka; -#if 0 - u32 psc_status; - - /* It seems this must be allowed to stabilise ?? */ - - while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804)); + /* Not sure what this does */ + + while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY)); + if (!(baka & 0x60000000)) return; /* - * Was this an ethernet event ? + * Process the read queue */ - - if(psc_status&0x60000000) - { -#endif - /* - * Process the read queue - */ - u16 psc_status = psc_read_word(PSC_ENETRD_CTL); + status = psc_read_word(PSC_ENETRD_CTL); - printk("mace68k_dma_intr: PSC_ENETRD_CTL = %04X\n", (uint) psc_status); - - if (psc_status & 0x2000) { - mace68k_rxdma_reset(dev); - mp->rx_done = 0; - } else if (psc_status & 0x100) { - int left; - - psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100); - left=psc_read_long(PSC_ENETRD_LEN + mp->rx_slot); - /* read packets */ - - while(mp->rx_done < left) - { - struct mace_frame *mf=((struct mace_frame *) - mp->rx_ring)+mp->rx_done++; - mace_dma_rx_frame(dev, mf); - } + if (status & 0x2000) { + mace_rxdma_reset(dev); + } else if (status & 0x0100) { + psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100); + + left = psc_read_long(PSC_ENETRD_LEN + mp->rx_slot); + head = N_RX_RING - left; + + /* Loop through the ring buffer and process new packages */ + + while (mp->rx_tail < head) { + mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800))); + mp->rx_tail++; + } - if(left == 0) /* Out of DMA room */ - { - psc_load_rxdma_base(mp->rx_slot, - (void *)virt_to_phys(mp->rx_ring)); - mp->rx_slot^=16; - mp->rx_done = 0; - } - else - { - psc_write_word(PSC_ENETRD_CMD+mp->rx_slot, - 0x9800); - } - + /* If we're out of buffers in this ring then switch to */ + /* the other set, otherwise just reactivate this one. */ + + if (!left) { + mace_load_rxdma_base(dev, mp->rx_slot); + mp->rx_slot ^= 0x10; + } else { + psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x9800); } + } - /* - * Process the write queue - */ - - psc_status = psc_read_word(PSC_ENETWR_CTL); - printk("mace68k_dma_intr: PSC_ENETWR_CTL = %04X\n", (uint) psc_status); + /* + * Process the write queue + */ - /* apple's driver seems to loop over this until neither */ - /* condition is true. - jmt */ + status = psc_read_word(PSC_ENETWR_CTL); - if (psc_status & 0x2000) { - mace68k_txdma_reset(dev); - } else if (psc_status & 0x0100) { - psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x0100); - mp->tx_slot ^=16; - mp->tx_count++; - dev->tbusy = 0; - mark_bh(NET_BH); - } -#if 0 + if (status & 0x2000) { + mace_txdma_reset(dev); + } else if (status & 0x0100) { + psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100); + mp->tx_sloti ^= 0x10; + mp->tx_count++; + netif_wake_queue(dev); } -#endif } + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/macsonic.c b/drivers/net/macsonic.c --- a/drivers/net/macsonic.c Wed Jul 24 14:03:36 2002 +++ b/drivers/net/macsonic.c Wed Jul 24 14:03:36 2002 @@ -20,6 +20,9 @@ * and duplicating packets. Needs more testing. * * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed. + * + * 00/10/31 sammy@oh.verio.com: Updated driver for 2.4 kernels, fixed problems + * on centris. */ #include @@ -46,6 +49,7 @@ #include #include #include +#include #include @@ -58,9 +62,21 @@ #include "sonic.h" +#define SONIC_READ(reg) \ + nubus_readl(base_addr+(reg)) +#define SONIC_WRITE(reg,val) \ + nubus_writel((val), base_addr+(reg)) +#define sonic_read(dev, reg) \ + nubus_readl((dev)->base_addr+(reg)) +#define sonic_write(dev, reg, val) \ + nubus_writel((val), (dev)->base_addr+(reg)) + + static int sonic_debug; static int sonic_version_printed; +static int reg_offset; + extern int macsonic_probe(struct net_device* dev); extern int mac_onboard_sonic_probe(struct net_device* dev); extern int mac_nubus_sonic_probe(struct net_device* dev); @@ -95,7 +111,7 @@ resource directories */ #define DAYNA_SONIC_MAC_ADDR 0xffe004 -#define SONIC_READ_PROM(addr) readb(prom_addr+addr) +#define SONIC_READ_PROM(addr) nubus_readb(prom_addr+addr) int __init macsonic_probe(struct net_device* dev) { @@ -125,36 +141,42 @@ int __init macsonic_init(struct net_device* dev) { - struct sonic_local* lp = (struct sonic_local *)dev->priv; + struct sonic_local* lp; int i; /* Allocate the entire chunk of memory for the descriptors. Note that this cannot cross a 64K boundary. */ for (i = 0; i < 20; i++) { unsigned long desc_base, desc_top; - if ((lp->sonic_desc = - kmalloc(SIZEOF_SONIC_DESC - * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_KERNEL | GFP_DMA)) == NULL) { + if((lp = kmalloc(sizeof(struct sonic_local), GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name); return -ENOMEM; } - desc_base = (unsigned long) lp->sonic_desc; - desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode); + + desc_base = (unsigned long) lp; + desc_top = desc_base + sizeof(struct sonic_local); if ((desc_top & 0xffff) >= (desc_base & 0xffff)) break; /* Hmm. try again (FIXME: does this actually work?) */ - kfree(lp->sonic_desc); + kfree(lp); printk(KERN_DEBUG "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n", dev->name, desc_base, desc_top); } - if (lp->sonic_desc == NULL) { + if (lp == NULL) { printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n", dev->name); return -ENOMEM; } + dev->priv = lp; + +#if 0 + /* this code is only here as a curiousity... mainly, where the + fuck did SONIC_BUS_SCALE come from, and what was it supposed + to do? the normal allocation works great for 32 bit stuffs.. */ + /* Now set up the pointers to point to the appropriate places */ lp->cda = lp->sonic_desc; lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode)); @@ -163,24 +185,33 @@ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS * SONIC_BUS_SCALE(lp->dma_bitmode)); +#endif + + memset(lp, 0, sizeof(struct sonic_local)); + + lp->cda_laddr = (unsigned int)&(lp->cda); + lp->tda_laddr = (unsigned int)lp->tda; + lp->rra_laddr = (unsigned int)lp->rra; + lp->rda_laddr = (unsigned int)lp->rda; + /* FIXME, maybe we should use skbs */ if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name); - kfree(lp->sonic_desc); - lp->sonic_desc = NULL; return -ENOMEM; } + lp->rba_laddr = (unsigned int)lp->rba; + { int rs, ds; /* almost always 12*4096, but let's not take chances */ rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096; /* almost always under a page, but let's not take chances */ - ds = ((SIZEOF_SONIC_DESC + 4095) / 4096) * 4096; + ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096; kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER); - kernel_set_cachemode(lp->sonic_desc, ds, IOMAP_NOCACHE_SER); + kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER); } #if 0 @@ -275,8 +306,8 @@ { /* Bwahahaha */ static int once_is_more_than_enough; - struct sonic_local* lp; int i; + int dma_bitmode; if (once_is_more_than_enough) return -ENODEV; @@ -333,8 +364,13 @@ if (dev == NULL) return -ENOMEM; - lp = (struct sonic_local*) dev->priv; - memset(lp, 0, sizeof(struct sonic_local)); + if(dev->priv) { + printk("%s: warning! sonic entering with priv already allocated!\n", + dev->name); + printk("%s: discarding, will attempt to reallocate\n", dev->name); + dev->priv = NULL; + } + /* Danger! My arms are flailing wildly! You *must* set this before using sonic_read() */ @@ -356,8 +392,11 @@ /* The PowerBook's SONIC is 16 bit always. */ if (macintosh_config->ident == MAC_MODEL_PB520) { - lp->reg_offset = 0; - lp->dma_bitmode = 0; + reg_offset = 0; + dma_bitmode = 0; + } else if (macintosh_config->ident == MAC_MODEL_C610) { + reg_offset = 0; + dma_bitmode = 1; } else { /* Some of the comm-slot cards are 16 bit. But some of them are not. The 32-bit cards use offset 2 and @@ -368,27 +407,41 @@ /* Technically this is not necessary since we zeroed it above */ - lp->reg_offset = 0; - lp->dma_bitmode = 0; + reg_offset = 0; + dma_bitmode = 0; sr = sonic_read(dev, SONIC_SR); if (sr == 0 || sr == 0xffff) { - lp->reg_offset = 2; + reg_offset = 2; /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */ sr = sonic_read(dev, SONIC_SR); - lp->dma_bitmode = 1; + dma_bitmode = 1; } printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - dev->name, sr, lp->dma_bitmode?32:16, lp->reg_offset); + dev->name, sr, dma_bitmode?32:16, reg_offset); } + - + /* this carries my sincere apologies -- by the time I got to updating + the driver, support for "reg_offsets" appeares nowhere in the sonic + code, going back for over a year. Fortunately, my Mac does't seem + to use whatever this was. + + If you know how this is supposed to be implemented, either fix it, + or contact me (sammy@oh.verio.com) to explain what it is. --Sam */ + + if(reg_offset) { + printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name); + return -ENODEV; + } + /* Software reset, then initialize control registers. */ sonic_write(dev, SONIC_CMD, SONIC_CR_RST); sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | - (lp->dma_bitmode ? SONIC_DCR_DW : 0)); + (dma_bitmode ? SONIC_DCR_DW : 0)); + /* This *must* be written back to in order to restore the extended programmable output bits */ sonic_write(dev, SONIC_DCR2, 0); @@ -452,7 +505,7 @@ u16 sonic_dcr; int id; int i; - int reg_offset, dma_bitmode; + int dma_bitmode; /* Find the first SONIC that hasn't been initialized already */ while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, @@ -538,8 +591,6 @@ memset(lp, 0, sizeof(struct sonic_local)); /* Danger! My arms are flailing wildly! You *must* set this before using sonic_read() */ - lp->reg_offset = reg_offset; - lp->dma_bitmode = dma_bitmode; dev->base_addr = base_addr; dev->irq = SLOT2IRQ(ndev->board->slot); @@ -552,6 +603,11 @@ printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset); + if(reg_offset) { + printk("%s: register offset unsupported. please fix this if you know what it is.\n", dev->name); + return -ENODEV; + } + /* Software reset, then initialize control registers. */ sonic_write(dev, SONIC_CMD, SONIC_CR_RST); sonic_write(dev, SONIC_DCR, sonic_dcr @@ -614,6 +670,9 @@ #define vdma_free(baz) #define sonic_chiptomem(bat) (bat) #define PHYSADDR(quux) (quux) + +#define sonic_request_irq request_irq +#define sonic_free_irq free_irq #include "sonic.c" diff -Nru a/drivers/net/plip.c b/drivers/net/plip.c --- a/drivers/net/plip.c Wed Jul 24 14:03:39 2002 +++ b/drivers/net/plip.c Wed Jul 24 14:03:39 2002 @@ -518,7 +518,7 @@ spin_unlock_irq(&nl->lock); if (error == HS_TIMEOUT) { DISABLE(dev->irq); - synchronize_irq(); + synchronize_irq(dev->irq); } disable_parport_interrupts (dev); netif_stop_queue (dev); @@ -840,7 +840,7 @@ if (c0 & 0x08) { spin_unlock_irq(&nl->lock); DISABLE(dev->irq); - synchronize_irq(); + synchronize_irq(dev->irq); if (nl->connection == PLIP_CN_RECEIVE) { /* Interrupted. We don't need to enable irq, @@ -1178,7 +1178,7 @@ netif_stop_queue (dev); DISABLE(dev->irq); - synchronize_irq(); + synchronize_irq(dev->irq); if (dev->irq == -1) { diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c --- a/drivers/net/sgiseeq.c Wed Jul 24 14:03:39 2002 +++ b/drivers/net/sgiseeq.c Wed Jul 24 14:03:39 2002 @@ -450,7 +450,7 @@ unsigned long flags; int err; - __save_and_cli(flags); + local_irq_save(flags); err = -EAGAIN; if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { @@ -464,7 +464,7 @@ netif_start_queue(dev); out: - __restore_flags(flags); + local_irq_restore(flags); return err; } diff -Nru a/drivers/net/sonic.h b/drivers/net/sonic.h --- a/drivers/net/sonic.h Wed Jul 24 14:03:35 2002 +++ b/drivers/net/sonic.h Wed Jul 24 14:03:35 2002 @@ -87,6 +87,7 @@ #define SONIC_FAET 0x2d #define SONIC_MPT 0x2e +#define SONIC_DCR2 0x3f /* * SONIC command bits diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c --- a/drivers/net/tulip/de2104x.c Wed Jul 24 14:03:37 2002 +++ b/drivers/net/tulip/de2104x.c Wed Jul 24 14:03:37 2002 @@ -1455,7 +1455,7 @@ /* Update the error counts. */ __de_get_stats(de); - synchronize_irq(); + synchronize_irq(dev->irq); de_clean_rings(de); de_init_hw(de); diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c --- a/drivers/net/wireless/orinoco.c Wed Jul 24 14:03:38 2002 +++ b/drivers/net/wireless/orinoco.c Wed Jul 24 14:03:38 2002 @@ -534,10 +534,10 @@ TRACE_ENTER(priv->ndev->name); - __cli(); /* FIXME: is this necessary? */ + local_irq_disable(); /* FIXME: is this necessary? */ set_bit(ORINOCO_STATE_DOIRQ, &priv->state); hermes_set_irqmask(hw, irqmask); - __sti(); + local_irq_enable(); TRACE_EXIT(priv->ndev->name); } diff -Nru a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c --- a/drivers/nubus/nubus.c Wed Jul 24 14:03:36 2002 +++ b/drivers/nubus/nubus.c Wed Jul 24 14:03:36 2002 @@ -961,18 +961,18 @@ return strlen(ptr); } -static int nubus_read_proc(char *buf, char **start, off_t off, +static int nubus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int nprinted, len, begin = 0; - int slot,size; + int size = PAGE_SIZE; struct nubus_board* board; - len = sprintf(buf, "Nubus devices found:\n"); + len = sprintf(page, "Nubus devices found:\n"); /* Walk the list of NuBus boards */ for (board = nubus_boards; board != NULL; board = board->next) { - nprinted = sprint_nubus_board(board, buf + len, size - len); + nprinted = sprint_nubus_board(board, page + len, size - len); if (nprinted < 0) break; len += nprinted; @@ -983,10 +983,10 @@ if (len+begin >= off+count) break; } - if (slot==16 || len+begin < off) + if (len+begin < off) *eof = 1; off -= begin; - *start = buf + off; + *start = page + off; len -= off; if (len>count) len = count; @@ -1009,10 +1009,10 @@ } } -void __init nubus_init(void) +static int __init nubus_init(void) { if (!MACH_IS_MAC) - return; + return 0; /* Initialize the NuBus interrupts */ if (oss_present) { @@ -1038,6 +1038,7 @@ create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL); nubus_proc_init(); #endif + return 0; } subsys_initcall(nubus_init); diff -Nru a/drivers/parport/init.c b/drivers/parport/init.c --- a/drivers/parport/init.c Wed Jul 24 14:03:38 2002 +++ b/drivers/parport/init.c Wed Jul 24 14:03:38 2002 @@ -31,6 +31,7 @@ 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; diff -Nru a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c --- a/drivers/parport/parport_mfc3.c Wed Jul 24 14:03:37 2002 +++ b/drivers/parport/parport_mfc3.c Wed Jul 24 14:03:37 2002 @@ -332,7 +332,7 @@ int __init parport_mfc3_init(void) { struct parport *p; - int pias; + int pias = 0; struct pia *pp; struct zorro_dev *z = NULL; diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c --- a/drivers/parport/parport_pc.c Wed Jul 24 14:03:38 2002 +++ b/drivers/parport/parport_pc.c Wed Jul 24 14:03:38 2002 @@ -2406,7 +2406,9 @@ 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; if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); @@ -2418,10 +2420,12 @@ 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, priv->dma_buf, priv->dma_handle); +#endif /* CONFIG_PARPORT_PC_FIFO */ kfree (p->private_data); parport_unregister_port(p); kfree (ops); /* hope no-one cached it */ diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Wed Jul 24 14:03:39 2002 +++ b/drivers/pci/pci-driver.c Wed Jul 24 14:03:39 2002 @@ -41,8 +41,8 @@ struct pci_driver *drv; struct pci_dev *pci_dev; - drv = list_entry(dev->driver, struct pci_driver, driver); - pci_dev = list_entry(dev, struct pci_dev, dev); + drv = to_pci_driver(dev->driver); + pci_dev = to_pci_dev(dev); if (drv->probe) { const struct pci_device_id *id; @@ -60,7 +60,7 @@ static int pci_device_remove(struct device * dev) { - struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); + struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * drv = pci_dev->driver; if (drv) { @@ -73,7 +73,7 @@ static int pci_device_suspend(struct device * dev, u32 state, u32 level) { - struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev); + struct pci_dev * pci_dev = to_pci_dev(dev); int error = 0; if (pci_dev->driver) { @@ -87,7 +87,7 @@ static int pci_device_resume(struct device * dev, u32 level) { - struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev); + struct pci_dev * pci_dev = to_pci_dev(dev); if (pci_dev->driver) { if (level == RESUME_POWER_ON && pci_dev->driver->resume) @@ -175,8 +175,8 @@ */ static int pci_bus_match(struct device * dev, struct device_driver * drv) { - struct pci_dev * pci_dev = list_entry(dev, struct pci_dev, dev); - struct pci_driver * pci_drv = list_entry(drv,struct pci_driver,driver); + struct pci_dev * pci_dev = to_pci_dev(dev); + struct pci_driver * pci_drv = to_pci_driver(drv); const struct pci_device_id * ids = pci_drv->id_table; if (!ids) diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c --- a/drivers/pci/proc.c Wed Jul 24 14:03:35 2002 +++ b/drivers/pci/proc.c Wed Jul 24 14:03:35 2002 @@ -374,7 +374,7 @@ /* driverfs files */ static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off) { - struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); + struct pci_dev * pci_dev = to_pci_dev(dev); return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq); } @@ -386,7 +386,7 @@ static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off) { - struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev); + struct pci_dev * pci_dev = to_pci_dev(dev); char * str = buf; int i; diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c --- a/drivers/s390/block/dasd_ioctl.c Wed Jul 24 14:03:35 2002 +++ b/drivers/s390/block/dasd_ioctl.c Wed Jul 24 14:03:35 2002 @@ -447,11 +447,6 @@ return 0; } -static int dasd_ioctl_blkioctl(void *inp, int no, long args) -{ - return blk_ioctl(((struct inode *) inp)->i_bdev, no, args); -} - /* * Return device size in number of sectors. */ @@ -517,12 +512,12 @@ static int dasd_ioctl_getgeo(void *inp, int no, long args) { struct hd_geometry geo = { 0, }; + struct inode *inode = inp; dasd_devmap_t *devmap; dasd_device_t *device; - kdev_t kdev; + kdev_t kdev = inode->i_rdev; int rc; - kdev = ((struct inode *) inp)->i_rdev; devmap = dasd_devmap_from_kdev(kdev); device = (devmap != NULL) ? dasd_get_device(devmap) : ERR_PTR(-ENODEV); @@ -532,7 +527,7 @@ if (device != NULL && device->discipline != NULL && device->discipline->fill_geometry != NULL) { device->discipline->fill_geometry(device, &geo); - geo.start = get_start_sect(kdev); + geo.start = get_start_sect(inode->i_bdev); if (copy_to_user((struct hd_geometry *) args, &geo, sizeof (struct hd_geometry))) rc = -EFAULT; @@ -554,16 +549,10 @@ { BIODASDINFO2, dasd_ioctl_information }, { BIODASDPRRD, dasd_ioctl_read_profile }, { BIODASDPRRST, dasd_ioctl_reset_profile }, - { BLKELVGET, dasd_ioctl_blkioctl }, - { BLKELVSET, dasd_ioctl_blkioctl }, - { BLKFLSBUF, dasd_ioctl_blkioctl }, { BLKGETSIZE, dasd_ioctl_blkgetsize }, { BLKGETSIZE64, dasd_ioctl_blkgetsize64 }, - { BLKPG, dasd_ioctl_blkioctl }, - { BLKROGET, dasd_ioctl_blkioctl }, { BLKROSET, dasd_ioctl_set_ro }, { BLKRRPART, dasd_ioctl_rr_partition }, - { BLKSSZGET, dasd_ioctl_blkioctl }, { DASDAPIVER, dasd_ioctl_api_version }, { HDIO_GETGEO, dasd_ioctl_getgeo }, { -1, NULL } diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Wed Jul 24 14:03:39 2002 +++ b/drivers/s390/block/xpram.c Wed Jul 24 14:03:39 2002 @@ -342,14 +342,6 @@ if (idx >= xpram_devs) return -ENODEV; switch (cmd) { - case BLKGETSIZE: - /* Return the device size, expressed in sectors */ - return put_user(xpram_sizes[idx] << 1, (unsigned long *) arg); - case BLKGETSIZE64: - /* Return the device size, expressed in bytes */ - return put_user((u64) xpram_sizes[idx] << 10, (u64 *) arg); - case BLKFLSBUF: - return blk_ioctl(((struct inode *) inode)->i_bdev, cmd, arg); case BLKRRPART: /* re-read partition table: can't do it */ return -EINVAL; diff -Nru a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h --- a/drivers/s390/char/tubio.h Wed Jul 24 14:03:35 2002 +++ b/drivers/s390/char/tubio.h Wed Jul 24 14:03:35 2002 @@ -338,11 +338,10 @@ #define spin_trylock_irqsave(lock, flags) \ ({ \ int success; \ - __save_flags(flags); \ - __cli(); \ + local_irq_save(flags); \ success = spin_trylock(lock); \ if (success == 0) \ - __restore_flags(flags); \ + local_irq_restore(flags); \ success; \ }) #endif /* if not spin_trylock_irqsave */ diff -Nru a/drivers/s390/cio/s390io.c b/drivers/s390/cio/s390io.c --- a/drivers/s390/cio/s390io.c Wed Jul 24 14:03:39 2002 +++ b/drivers/s390/cio/s390io.c Wed Jul 24 14:03:39 2002 @@ -163,11 +163,10 @@ * function we resestablish the old environment. * * Note : as we don't need a system wide lock, therefore - * we shouldn't use cli(), but __cli() as this + * we shouldn't use cli(), but local_irq_save() as this * affects the current CPU only. */ - __save_flags (flags); - __cli (); + local_irq_save(flags); /* * disable all interrupts @@ -204,7 +203,7 @@ init_IRQ_complete = 1; - __restore_flags (flags); + local_irq_restore (flags); return; } @@ -578,10 +577,9 @@ * also require to run disabled. * * Note : as no global lock is required, we must not use - * cli(), but __cli() instead. + * cli(), but local_irq_save() instead. */ - __save_flags (flags); - __cli (); + local_irq_save(flags); rdc_ccw = &ioinfo[irq]->senseccw; @@ -643,7 +641,7 @@ } - __restore_flags (flags); + local_irq_restore (flags); /* * on success we update the user input parms @@ -720,8 +718,7 @@ int emulated = 0; /* no i/O handler installed */ int retry = 5; /* retry count */ - __save_flags (flags); - __cli (); + local_irq_save(flags); if (!ioinfo[irq]->ui.flags.ready) { pdevstat = &devstat; @@ -816,7 +813,7 @@ } - __restore_flags (flags); + local_irq_restore (flags); } diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c --- a/drivers/s390/net/lcs.c Wed Jul 24 14:03:36 2002 +++ b/drivers/s390/net/lcs.c Wed Jul 24 14:03:36 2002 @@ -968,7 +968,7 @@ #if LINUX_VERSION_CODE<=KERNEL_VERSION(2,2,16) /* tq_scheduler sometimes leaves interrupts disabled from do * bottom half */ - __sti(); + local_irq_enable(); #endif if (kernel_thread((int (*)(void *)) drvr_globals->kernel_thread_routine, (void *) drvr_globals, SIGCHLD) < 0) { diff -Nru a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c --- a/drivers/s390/s390mach.c Wed Jul 24 14:03:39 2002 +++ b/drivers/s390/s390mach.c Wed Jul 24 14:03:39 2002 @@ -254,8 +254,7 @@ found = 0; /* init ... */ - __save_flags(flags); - __cli(); + local_irq_save(flags); do { @@ -311,7 +310,7 @@ } while (pmache); - __restore_flags(flags); + local_irq_restore(flags); } while (1); diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c --- a/drivers/sbus/char/jsflash.c Wed Jul 24 14:03:38 2002 +++ b/drivers/sbus/char/jsflash.c Wed Jul 24 14:03:38 2002 @@ -464,14 +464,6 @@ case BLKGETSIZE64: return put_user(jsfd_bytesizes[dev], (u64 *) arg); -#if 0 - case BLKROSET: - case BLKROGET: - case BLKSSZGET: - return blk_ioctl(inode->i_bdev, cmd, arg); -#endif - - /* case BLKFLSBUF: */ /* Program, then read, what happens? Stale? */ default: ; } return -ENOTTY; diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/3w-xxxx.c Wed Jul 24 14:03:39 2002 @@ -2084,7 +2084,7 @@ } /* End tw_reset_sequence() */ /* This funciton returns unit geometry in cylinders/heads/sectors */ -int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[]) +int tw_scsi_biosparam(Disk *disk, struct block_device *dev, int geom[]) { int heads, sectors, cylinders; TW_Device_Extension *tw_dev; diff -Nru a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h --- a/drivers/scsi/3w-xxxx.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/3w-xxxx.h Wed Jul 24 14:03:36 2002 @@ -56,7 +56,6 @@ #include #include -#include /* AEN strings */ static char *tw_aen_string[] = { @@ -445,7 +444,7 @@ int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id); int tw_reset_device_extension(TW_Device_Extension *tw_dev); int tw_reset_sequence(TW_Device_Extension *tw_dev); -int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[]); +int tw_scsi_biosparam(Disk *disk, struct block_device *dev, int geom[]); int tw_scsi_detect(Scsi_Host_Template *tw_host); int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt); int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt); diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c --- a/drivers/scsi/53c7xx.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/53c7xx.c Wed Jul 24 14:03:39 2002 @@ -1144,8 +1144,8 @@ return -1; } - printk("scsi-ncr53c7xx : %s at memory 0x%x, io 0x%x, irq %d", - chip_str, (unsigned) base, io_port, irq); + printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d", + chip_str, base, io_port, irq); if (dma == DMA_NONE) printk("\n"); else @@ -3459,9 +3459,10 @@ for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, cmd_dataout += 4, ++i) { - u32 vbuf = cmd->use_sg ? - (u32)(((struct scatterlist *)cmd->buffer)[i].address) : - (u32)(cmd->request_buffer); + u32 vbuf = cmd->use_sg + ? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+ + ((struct scatterlist *)cmd->buffer)[i].offset + : (u32)(cmd->request_buffer); u32 bbuf = virt_to_bus((void *)vbuf); u32 count = cmd->use_sg ? ((struct scatterlist *)cmd->buffer)[i].length : @@ -5428,16 +5429,16 @@ if ((buffers = cmd->use_sg)) { for (offset = 0, segment = (struct scatterlist *) cmd->buffer; - buffers && !((found = ((ptr >= segment->address) && - (ptr < (segment->address + segment->length))))); + buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) && + (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length))))); --buffers, offset += segment->length, ++segment) #if 0 printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->host->host_no, saved, segment->address); + cmd->host->host_no, saved, page_address(segment->page+segment->offset); #else ; #endif - offset += ptr - segment->address; + offset += ptr - ((char *)page_address(segment->page)+segment->offset); } else { found = 1; offset = ptr - (char *) (cmd->request_buffer); diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/BusLogic.c Wed Jul 24 14:03:39 2002 @@ -4110,7 +4110,7 @@ the BIOS, and a warning may be displayed. */ -int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device, +int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, struct block_device *bdev, int *Parameters) { BusLogic_HostAdapter_T *HostAdapter = @@ -4138,7 +4138,7 @@ } DiskParameters->Cylinders = Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors); - buf = scsi_bios_ptable(Device); + buf = scsi_bios_ptable(bdev); if (buf == NULL) return 0; /* If the boot sector partition table flag is valid, search for a partition diff -Nru a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h --- a/drivers/scsi/BusLogic.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/BusLogic.h Wed Jul 24 14:03:38 2002 @@ -34,7 +34,6 @@ of the Linux Kernel and SCSI Subsystem. */ -typedef kdev_t KernelDevice_T; typedef unsigned long ProcessorFlags_T; typedef struct pt_regs Registers_T; typedef struct partition PartitionTable_T; @@ -58,7 +57,7 @@ void (*CompletionRoutine)(SCSI_Command_T *)); extern int BusLogic_AbortCommand(SCSI_Command_T *); extern int BusLogic_ResetCommand(SCSI_Command_T *, unsigned int); -extern int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); +extern int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, struct block_device *, int *); extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c --- a/drivers/scsi/NCR5380.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/NCR5380.c Wed Jul 24 14:03:36 2002 @@ -337,7 +337,8 @@ if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *) cmd->SCp.buffer->address; + cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ + cmd->SCp.buffer->offset; cmd->SCp.this_residual = cmd->SCp.buffer->length; } else { cmd->SCp.buffer = NULL; @@ -2308,7 +2309,8 @@ ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = cmd->SCp.buffer->address; + cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ + cmd->SCp.buffer->offset; dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); } /* diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/NCR53c406a.c Wed Jul 24 14:03:38 2002 @@ -760,7 +760,7 @@ } int -NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){ +NCR53c406a_biosparm(Scsi_Disk *disk, struct block_device *dev, int* info_array){ int size; DEB(printk("NCR53c406a_biosparm called\n")); diff -Nru a/drivers/scsi/NCR53c406a.h b/drivers/scsi/NCR53c406a.h --- a/drivers/scsi/NCR53c406a.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/NCR53c406a.h Wed Jul 24 14:03:37 2002 @@ -50,7 +50,7 @@ int NCR53c406a_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int NCR53c406a_abort(Scsi_Cmnd *); int NCR53c406a_reset(Scsi_Cmnd *, unsigned int); -int NCR53c406a_biosparm(Disk *, kdev_t, int []); +int NCR53c406a_biosparm(Disk *, struct block_device *, int []); #endif /* _NCR53C406A_H */ diff -Nru a/drivers/scsi/README.st b/drivers/scsi/README.st --- a/drivers/scsi/README.st Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/README.st Wed Jul 24 14:03:36 2002 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai M{kisara (email Kai.Makisara@metla.fi) -Last modified: Tue Jun 18 18:13:50 2002 by makisara +Last modified: Mon Jul 15 16:30:40 2002 by makisara BASICS @@ -118,7 +118,6 @@ memory having sizes 2^n * (page size). Because of this the actual buffer size may be larger than the minimum allowable buffer size. - 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. @@ -163,12 +162,24 @@ extending the buffer will always fail. +EOM BEHAVIOUR WHEN WRITING + +When the end of medium early warning is encountered, the current write +is finished and the number of bytes is returned. The next write +returns -1 and errno is set to ENOSPC. To enable writing a trailer, +the next write is allowed to proceed and, if successful, the number of +bytes is returned. After this, -1 and the number of bytes are +alternately returned until the physical end of medium (or some other +error) is encountered. + + MODULE PARAMETERS The buffer size, write threshold, and the maximum number of allocated buffers are configurable when the driver is loaded as a module. The keywords are: -buffer_kbs=xxx the buffer size in kilobytes is set to xxx +buffer_kbs=xxx the buffer size for fixed block mode is set + to xxx kilobytes write_threshold_kbs=xxx the write threshold in kilobytes set to xxx max_buffers=xxx the maximum number of tape buffer set to xxx max_sg_segs=xxx the maximum number of scatter/gather @@ -188,17 +199,15 @@ mark. The definition is prepended by the string st=. Here is an example: - st=buffer_kbs:64,max_buffers:2 + st=buffer_kbs:64,write_threhold_kbs:60 The following syntax used by the old kernel versions is also supported: - st=aa[,bb[,cc[,dd]]] + st=aa[,bb[,dd]] where - aa is the buffer size in 1024 byte units + aa is the buffer size for fixed block mode in 1024 byte units bb is the write threshold in 1024 byte units - cc is the maximum number of tape buffers to allocate (the number of - buffers is bounded also by the number of drives detected) dd is the maximum number of scatter/gather segments @@ -231,7 +240,9 @@ MTNOP Do nothing except flush the buffers. MTRETEN Re-tension tape. MTEOM Space to end of recorded data. -MTERASE Erase tape. +MTERASE Erase tape. If the argument is zero, the short erase command + is used. The long erase command is used with all other values + of the argument. MTSEEK Seek to tape block count. Uses Tandberg-compatible seek (QFA) for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and block numbers in the status are not valid after a seek. diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/advansys.c Wed Jul 24 14:03:37 2002 @@ -6114,7 +6114,7 @@ * ip[2]: cylinders */ int -advansys_biosparam(Disk *dp, kdev_t dep, int ip[]) +advansys_biosparam(Disk *dp, struct block_device *dep, int ip[]) { asc_board_t *boardp; diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h --- a/drivers/scsi/advansys.h Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/advansys.h Wed Jul 24 14:03:39 2002 @@ -52,7 +52,7 @@ const char *advansys_info(struct Scsi_Host *); int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int advansys_reset(Scsi_Cmnd *); -int advansys_biosparam(Disk *, kdev_t, int[]); +int advansys_biosparam(Disk *, struct block_device *, int[]); #ifdef CONFIG_PROC_FS #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,28) extern struct proc_dir_entry proc_scsi_advansys; diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c --- a/drivers/scsi/aha152x.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/aha152x.c Wed Jul 24 14:03:35 2002 @@ -1830,7 +1830,7 @@ * Return the "logical geometry" * */ -int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) +int aha152x_biosparam(Scsi_Disk * disk, struct block_device *bdev, int *info_array) { struct Scsi_Host *shpnt = disk->device->host; @@ -1844,7 +1844,7 @@ int info[3]; /* try to figure out the geometry from the partition table */ - if (scsicam_bios_param(disk, dev, info) < 0 || + if (scsicam_bios_param(disk, bdev, info) < 0 || !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) { if (EXT_TRANS) { printk(KERN_NOTICE diff -Nru a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h --- a/drivers/scsi/aha152x.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/aha152x.h Wed Jul 24 14:03:38 2002 @@ -20,7 +20,7 @@ int aha152x_device_reset(Scsi_Cmnd *); int aha152x_bus_reset(Scsi_Cmnd *); int aha152x_host_reset(Scsi_Cmnd *); -int aha152x_biosparam(Disk *, kdev_t, int*); +int aha152x_biosparam(Disk *, struct block_device *, int*); int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); /* number of queueable commands diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/aha1542.c Wed Jul 24 14:03:35 2002 @@ -1783,7 +1783,7 @@ #include "sd.h" -static int aha1542_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip) +static int aha1542_biosparam(Scsi_Disk * disk, struct block_device *dev, int *ip) { int translation_algorithm; int size = disk->capacity; diff -Nru a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h --- a/drivers/scsi/aha1542.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/aha1542.h Wed Jul 24 14:03:36 2002 @@ -32,7 +32,6 @@ */ #include -#include /* I/O Port interface 4.2 */ /* READ */ @@ -141,7 +140,7 @@ static int aha1542_old_abort(Scsi_Cmnd * SCpnt); static int aha1542_old_reset(Scsi_Cmnd *, unsigned int); #endif -static int aha1542_biosparam(Disk *, kdev_t, int*); +static int aha1542_biosparam(Disk *, struct block_device *, int*); #define AHA1542_MAILBOXES 8 #define AHA1542_SCATTER 16 diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/aha1740.c Wed Jul 24 14:03:36 2002 @@ -590,7 +590,7 @@ return SCSI_RESET_PUNT; } -int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip) +int aha1740_biosparam(Disk * disk, struct block_device *dev, int* ip) { int size = disk->capacity; int extended = HOSTDATA(disk->device->host)->translation; diff -Nru a/drivers/scsi/aha1740.h b/drivers/scsi/aha1740.h --- a/drivers/scsi/aha1740.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/aha1740.h Wed Jul 24 14:03:38 2002 @@ -11,7 +11,6 @@ */ #include -#include /* Eisa Enhanced mode operation - slot locating and addressing */ #define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ @@ -158,7 +157,7 @@ int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int aha1740_abort(Scsi_Cmnd *); int aha1740_reset(Scsi_Cmnd *, unsigned int); -int aha1740_biosparam(Disk *, kdev_t, int*); +int aha1740_biosparam(Disk *, struct block_device *, int*); int aha1740_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c --- a/drivers/scsi/aic7xxx/aic7xxx_linux.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c Wed Jul 24 14:03:38 2002 @@ -2722,7 +2722,7 @@ * Return the disk geometry for the given SCSI device. */ int -ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[]) +ahc_linux_biosparam(Disk *disk, struct block_device *bdev, int geom[]) { int heads; int sectors; @@ -2733,7 +2733,7 @@ unsigned char *buf; ahc = *((struct ahc_softc **)disk->device->host->hostdata); - buf = scsi_bios_ptable(dev); + buf = scsi_bios_ptable(bdev); if (buf) { ret = scsi_partsize(buf, disk->capacity, diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h --- a/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Wed Jul 24 14:03:37 2002 @@ -47,7 +47,7 @@ int ahc_linux_detect(Scsi_Host_Template *); int ahc_linux_release(struct Scsi_Host *); const char *ahc_linux_info(struct Scsi_Host *); -int ahc_linux_biosparam(Disk *, kdev_t, int[]); +int ahc_linux_biosparam(Disk *, struct block_device *, int[]); int ahc_linux_bus_reset(Scsi_Cmnd *); int ahc_linux_dev_reset(Scsi_Cmnd *); int ahc_linux_abort(Scsi_Cmnd *); diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h --- a/drivers/scsi/aic7xxx_old/aic7xxx.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/aic7xxx_old/aic7xxx.h Wed Jul 24 14:03:35 2002 @@ -58,7 +58,7 @@ } extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); +extern int aic7xxx_biosparam(Disk *, struct block_device *, int[]); extern int aic7xxx_detect(Scsi_Host_Template *); extern int aic7xxx_command(Scsi_Cmnd *); extern int aic7xxx_reset(Scsi_Cmnd *, unsigned int); diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/aic7xxx_old.c Wed Jul 24 14:03:37 2002 @@ -11719,14 +11719,14 @@ * Return the disk geometry for the given SCSI device. *-F*************************************************************************/ int -aic7xxx_biosparam(Disk *disk, kdev_t dev, int geom[]) +aic7xxx_biosparam(Disk *disk, struct block_device *bdev, int geom[]) { int heads, sectors, cylinders, ret; struct aic7xxx_host *p; unsigned char *buf; p = (struct aic7xxx_host *) disk->device->host->hostdata; - buf = scsi_bios_ptable(dev); + buf = scsi_bios_ptable(bdev); if ( buf ) { diff -Nru a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c --- a/drivers/scsi/atari_NCR5380.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/atari_NCR5380.c Wed Jul 24 14:03:38 2002 @@ -474,8 +474,8 @@ for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; cmd->SCp.buffers_residual && - virt_to_phys(cmd->SCp.buffer[1].address) == endaddr; ) { - + virt_to_phys(page_address(cmd->SCp.buffer[1].page)+ + cmd->SCp.buffer[1].offset) == endaddr; ) { MER_PRINTK("VTOP(%p) == %08lx -> merging\n", cmd->SCp.buffer[1].address, endaddr); #if (NDEBUG & NDEBUG_MERGING) @@ -512,7 +512,8 @@ if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *) cmd->SCp.buffer->address; + cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+ + cmd->SCp.buffer->offset; cmd->SCp.this_residual = cmd->SCp.buffer->length; /* ++roman: Try to merge some scatter-buffers if they are at * contiguous physical addresses. @@ -2060,7 +2061,8 @@ ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = cmd->SCp.buffer->address; + cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ + cmd->SCp.buffer->offset; /* ++roman: Try to merge some scatter-buffers if * they are at contiguous physical addresses. */ diff -Nru a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h --- a/drivers/scsi/atari_scsi.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/atari_scsi.h Wed Jul 24 14:03:38 2002 @@ -258,8 +258,6 @@ #define NCR_PRINT_STATUS(mask) \ ((NDEBUG & (mask)) ? NCR5380_print_status(instance) : (void)0) -#define NDEBUG_ANY 0xffffffff - #endif /* ndef ASM */ #endif /* ATARI_SCSI_H */ diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/atp870u.c Wed Jul 24 14:03:37 2002 @@ -2835,7 +2835,7 @@ #include "sd.h" -int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip) +int atp870u_biosparam(Scsi_Disk * disk, struct block_device *dev, int *ip) { int heads, sectors, cylinders; diff -Nru a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h --- a/drivers/scsi/atp870u.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/atp870u.h Wed Jul 24 14:03:35 2002 @@ -11,7 +11,6 @@ */ #include -#include /* I/O Port */ @@ -23,7 +22,7 @@ int atp870u_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); int atp870u_abort(Scsi_Cmnd *); int atp870u_reset(Scsi_Cmnd *, unsigned int); -int atp870u_biosparam(Disk *, kdev_t, int *); +int atp870u_biosparam(Disk *, struct block_device *, int *); int atp870u_release(struct Scsi_Host *); void send_s870(unsigned char); diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c --- a/drivers/scsi/bvme6000.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/bvme6000.c Wed Jul 24 14:03:36 2002 @@ -23,9 +23,9 @@ #include -extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, - unsigned long base, int io_port, int irq, int dma, - long long options, int clock); +extern int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, int chip, + unsigned long base, int io_port, int irq, int dma, + long long options, int clock); int bvme6000_scsi_detect(Scsi_Host_Template *tpnt) { diff -Nru a/drivers/scsi/cpqfcTS.h b/drivers/scsi/cpqfcTS.h --- a/drivers/scsi/cpqfcTS.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/cpqfcTS.h Wed Jul 24 14:03:37 2002 @@ -12,7 +12,7 @@ extern int cpqfcTS_reset(Scsi_Cmnd *, unsigned int); extern int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd); extern int cpqfcTS_eh_device_reset(Scsi_Cmnd *); -extern int cpqfcTS_biosparam(Disk *, kdev_t, int[]); +extern int cpqfcTS_biosparam(Disk *, struct block_device *, int[]); extern int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg); // note: since Tachyon TS supports an extended scatter/gather diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/cpqfcTSinit.c Wed Jul 24 14:03:35 2002 @@ -1625,7 +1625,7 @@ (from hosts.h) */ -int cpqfcTS_biosparam(Disk *disk, kdev_t n, int ip[]) +int cpqfcTS_biosparam(Disk *disk, struct block_device *n, int ip[]) { int size = disk->capacity; diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h --- a/drivers/scsi/dc390.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/dc390.h Wed Jul 24 14:03:36 2002 @@ -39,7 +39,7 @@ extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int DC390_abort(Scsi_Cmnd *cmd); extern int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags); -extern int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]); +extern int DC390_bios_param(Disk *disk, struct block_device *dev, int geom[]); #ifdef MODULE static int DC390_release(struct Scsi_Host *); diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/dpt_i2o.c Wed Jul 24 14:03:37 2002 @@ -453,7 +453,7 @@ return adpt_scsi_to_i2o(pHba, cmd, pDev); } -static int adpt_bios_param(Disk* disk, kdev_t dev, int geom[]) +static int adpt_bios_param(Disk* disk, struct block_device *dev, int geom[]) { int heads=-1; int sectors=-1; diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h --- a/drivers/scsi/dpti.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/dpti.h Wed Jul 24 14:03:35 2002 @@ -45,7 +45,7 @@ static int adpt_release(struct Scsi_Host *host); static const char *adpt_info(struct Scsi_Host *pSHost); -static int adpt_bios_param(Disk * disk, kdev_t dev, int geom[]); +static int adpt_bios_param(Disk * disk, struct block_device *dev, int geom[]); static int adpt_bus_reset(Scsi_Cmnd* cmd); static int adpt_device_reset(Scsi_Cmnd* cmd); diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/dtc.c Wed Jul 24 14:03:39 2002 @@ -295,7 +295,7 @@ } /* - * Function : int dtc_biosparam(Disk * disk, kdev_t dev, int *ip) + * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip) * * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for * the specified device / size. @@ -314,7 +314,7 @@ * and matching the H_C_S coordinates to what DOS uses. */ -int dtc_biosparam(Disk * disk, kdev_t dev, int * ip) +int dtc_biosparam(Disk * disk, struct block_device *dev, int * ip) { int size = disk->capacity; diff -Nru a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h --- a/drivers/scsi/dtc.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/dtc.h Wed Jul 24 14:03:36 2002 @@ -30,7 +30,7 @@ #ifndef ASM int dtc_abort(Scsi_Cmnd *); -int dtc_biosparam(Disk *, kdev_t, int*); +int dtc_biosparam(Disk *, struct block_device *, int*); int dtc_detect(Scsi_Host_Template *); int dtc_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int dtc_reset(Scsi_Cmnd *, unsigned int reset_flags); diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/eata.c Wed Jul 24 14:03:39 2002 @@ -1803,10 +1803,10 @@ return do_reset(SCarg); } -int eata2x_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { +int eata2x_biosparam(Disk *disk, struct block_device *bdev, int *dkinfo) { int size = disk->capacity; - if (ext_tran || (scsicam_bios_param(disk, dev, dkinfo) < 0)) { + if (ext_tran || (scsicam_bios_param(disk, bdev, dkinfo) < 0)) { dkinfo[0] = 255; dkinfo[1] = 63; dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h --- a/drivers/scsi/eata.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/eata.h Wed Jul 24 14:03:36 2002 @@ -11,7 +11,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int eata2x_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *); -int eata2x_biosparam(Disk *, kdev_t, int *); +int eata2x_biosparam(Disk *, struct block_device *, int *); #define EATA_VERSION "7.22.00" diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/fd_mcs.c Wed Jul 24 14:03:37 2002 @@ -1383,9 +1383,8 @@ #include "sd.h" #include -int fd_mcs_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ) +int fd_mcs_biosparam( Scsi_Disk *disk, struct block_device *bdev, int *info_array ) { - int drive; unsigned char buf[512 + sizeof( int ) * 2]; int size = disk->capacity; int *sizes = (int *)buf; @@ -1394,8 +1393,6 @@ int retcode; /* BIOS >= 3.4 for MCA cards */ - drive = MINOR(dev) / 16; - /* This algorithm was provided by Future Domain (much thanks!). */ sizes[0] = 0; /* zero bytes out */ diff -Nru a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h --- a/drivers/scsi/fd_mcs.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/fd_mcs.h Wed Jul 24 14:03:36 2002 @@ -28,7 +28,7 @@ extern int fd_mcs_abort( Scsi_Cmnd * ); extern int fd_mcs_reset( Scsi_Cmnd *, unsigned int ); extern int fd_mcs_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); -extern int fd_mcs_biosparam( Disk *, kdev_t, int * ); +extern int fd_mcs_biosparam( Disk *, struct block_device *, int * ); extern int fd_mcs_proc_info( char *, char **, off_t, int, int, int ); extern const char *fd_mcs_info(struct Scsi_Host *); diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/fdomain.c Wed Jul 24 14:03:36 2002 @@ -1874,7 +1874,7 @@ #include "sd.h" #include -int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ) +int fdomain_16x0_biosparam( Scsi_Disk *disk, struct block_device *bdev, int *info_array ) { int drive; unsigned char buf[512 + sizeof (Scsi_Ioctl_Command)]; @@ -1933,11 +1933,11 @@ 0x0a bytes long. Heads are one less than we need to report. */ - if (major(dev) != SCSI_DISK0_MAJOR) { + if (MAJOR(bdev->bd_dev) != SCSI_DISK0_MAJOR) { printk("scsi: fdomain_16x0_biosparam: too many disks"); return 0; } - drive = minor(dev) >> 4; + drive = MINOR(bdev->bd_dev) >> 4; if (bios_major == 2) { switch (Quantum) { diff -Nru a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h --- a/drivers/scsi/fdomain.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/fdomain.h Wed Jul 24 14:03:37 2002 @@ -31,7 +31,7 @@ const char *fdomain_16x0_info( struct Scsi_Host * ); int fdomain_16x0_reset( Scsi_Cmnd *, unsigned int ); int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); -int fdomain_16x0_biosparam( Disk *, kdev_t, int * ); +int fdomain_16x0_biosparam( Disk *, struct block_device *, int * ); int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, int length, int hostno, int inout ); int fdomain_16x0_release( struct Scsi_Host *shpnt ); diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/g_NCR5380.c Wed Jul 24 14:03:36 2002 @@ -512,7 +512,7 @@ * Locks: none */ -int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip) +int generic_NCR5380_biosparam(Disk * disk, struct block_device *dev, int *ip) { int size = disk->capacity; ip[0] = 64; diff -Nru a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h --- a/drivers/scsi/g_NCR5380.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/g_NCR5380.h Wed Jul 24 14:03:35 2002 @@ -53,7 +53,7 @@ int length, int hostno, int inout); const char* generic_NCR5380_info(struct Scsi_Host *); #ifdef BIOSPARAM -int generic_NCR5380_biosparam(Disk *, kdev_t, int *); +int generic_NCR5380_biosparam(Disk *, struct block_device *, int *); #endif int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout); diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/gdth.c Wed Jul 24 14:03:35 2002 @@ -4512,11 +4512,7 @@ } #endif -#if LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) -#else -int gdth_bios_param(Disk *disk,int dev,int *ip) -#endif +int gdth_bios_param(Disk *disk,struct block_device *bdev,int *ip) { unchar b, t; int hanum; diff -Nru a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h --- a/drivers/scsi/gdth.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/gdth.h Wed Jul 24 14:03:37 2002 @@ -1031,8 +1031,7 @@ #endif const char *gdth_info(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= 0x020322 -int gdth_bios_param(Disk *,kdev_t,int *); +int gdth_bios_param(Disk *,struct block_device *,int *); int gdth_proc_info(char *,char **,off_t,int,int,int); int gdth_eh_abort(Scsi_Cmnd *scp); int gdth_eh_device_reset(Scsi_Cmnd *scp); @@ -1060,84 +1059,6 @@ present: 0, \ unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING } - -#elif LINUX_VERSION_CODE >= 0x02015F -int gdth_bios_param(Disk *,kdev_t,int *); -extern struct proc_dir_entry proc_scsi_gdth; -int gdth_proc_info(char *,char **,off_t,int,int,int); -int gdth_eh_abort(Scsi_Cmnd *scp); -int gdth_eh_device_reset(Scsi_Cmnd *scp); -int gdth_eh_bus_reset(Scsi_Cmnd *scp); -int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { proc_dir: &proc_scsi_gdth, \ - proc_info: gdth_proc_info, \ - name: "GDT SCSI Disk Array Controller",\ - detect: gdth_detect, \ - release: gdth_release, \ - info: gdth_info, \ - command: NULL, \ - queuecommand: gdth_queuecommand, \ - eh_abort_handler: gdth_eh_abort, \ - eh_device_reset_handler: gdth_eh_device_reset, \ - eh_bus_reset_handler: gdth_eh_bus_reset, \ - eh_host_reset_handler: gdth_eh_host_reset, \ - abort: gdth_abort, \ - reset: gdth_reset, \ - bios_param: gdth_bios_param, \ - can_queue: GDTH_MAXCMDS, \ - this_id: -1, \ - sg_tablesize: GDTH_MAXSG, \ - cmd_per_lun: GDTH_MAXC_P_L, \ - present: 0, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING } - -#elif LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *,kdev_t,int *); -extern struct proc_dir_entry proc_scsi_gdth; -int gdth_proc_info(char *,char **,off_t,int,int,int); -#define GDTH { NULL, NULL, \ - &proc_scsi_gdth, \ - gdth_proc_info, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - NULL, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} - -#else -int gdth_bios_param(Disk *,int,int *); -#define GDTH { NULL, NULL, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - NULL, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} -#endif #endif diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/hosts.h Wed Jul 24 14:03:37 2002 @@ -210,9 +210,9 @@ * This function determines the bios parameters for a given * harddisk. These tend to be numbers that are made up by * the host adapter. Parameters: - * size, device number, list (heads, sectors, cylinders) + * size, device, list (heads, sectors, cylinders) */ - int (* bios_param)(Disk *, kdev_t, int []); + int (* bios_param)(Disk *, struct block_device *, int []); /* diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/ibmmca.c Wed Jul 24 14:03:36 2002 @@ -2382,7 +2382,7 @@ return SCSI_RESET_SUCCESS; } -int ibmmca_biosparam (Disk * disk, kdev_t dev, int *info) +int ibmmca_biosparam (Disk * disk, struct block_device *dev, int *info) { info[0] = 64; info[1] = 32; diff -Nru a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h --- a/drivers/scsi/ibmmca.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/ibmmca.h Wed Jul 24 14:03:36 2002 @@ -17,7 +17,7 @@ extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int ibmmca_abort (Scsi_Cmnd *); extern int ibmmca_reset (Scsi_Cmnd *, unsigned int); -extern int ibmmca_biosparam (Disk *, kdev_t, int *); +extern int ibmmca_biosparam (Disk *, struct block_device *, int *); /*structure for /proc filesystem */ extern struct proc_dir_entry proc_scsi_ibmmca; diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/ide-scsi.c Wed Jul 24 14:03:35 2002 @@ -711,7 +711,7 @@ return SUCCESS; } -static int idescsi_bios(Disk *disk, kdev_t dev, int *parm) +static int idescsi_bios(Disk *disk, struct block_device *dev, int *parm) { idescsi_scsi_t *scsi = idescsi_private(disk->device->host); struct ata_device *drive = scsi->drive; diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/imm.c Wed Jul 24 14:03:39 2002 @@ -1117,7 +1117,7 @@ * be done in sd.c. Even if it gets fixed there, this will still * work. */ -int imm_biosparam(Disk * disk, kdev_t dev, int ip[]) +int imm_biosparam(Disk * disk, struct block_device *dev, int ip[]) { ip[0] = 0x40; ip[1] = 0x20; diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h --- a/drivers/scsi/imm.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/imm.h Wed Jul 24 14:03:35 2002 @@ -162,7 +162,7 @@ int imm_abort(Scsi_Cmnd *); int imm_reset(Scsi_Cmnd *); int imm_proc_info(char *, char **, off_t, int, int, int); -int imm_biosparam(Disk *, kdev_t, int *); +int imm_biosparam(Disk *, struct block_device *, int *); #define IMM { proc_name: "imm", \ proc_info: imm_proc_info, \ diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/in2000.c Wed Jul 24 14:03:39 2002 @@ -2158,7 +2158,7 @@ * supposed to do... */ -int in2000_biosparam(Disk *disk, kdev_t dev, int *iinfo) +int in2000_biosparam(Disk *disk, struct block_device *dev, int *iinfo) { int size; diff -Nru a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h --- a/drivers/scsi/in2000.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/in2000.h Wed Jul 24 14:03:35 2002 @@ -402,7 +402,7 @@ int in2000_abort(Scsi_Cmnd *); void in2000_setup(char *, int *) in2000__INIT; int in2000_proc_info(char *, char **, off_t, int, int, int); -int in2000_biosparam(struct scsi_disk *, kdev_t, int *); +int in2000_biosparam(struct scsi_disk *, struct block_device *, int *); int in2000_reset(Scsi_Cmnd *, unsigned int); diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/ini9100u.c Wed Jul 24 14:03:37 2002 @@ -583,7 +583,7 @@ /* * Return the "logical geometry" */ -int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) +int i91u_biosparam(Scsi_Disk * disk, struct block_device *dev, int *info_array) { HCS *pHcb; /* Point to Host adapter control block */ TCS *pTcb; diff -Nru a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h --- a/drivers/scsi/ini9100u.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/ini9100u.h Wed Jul 24 14:03:38 2002 @@ -84,7 +84,7 @@ extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); extern int i91u_reset(Scsi_Cmnd *, unsigned int); -extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ +extern int i91u_biosparam(Scsi_Disk *, struct block_device *, int *); #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g" diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/inia100.c Wed Jul 24 14:03:37 2002 @@ -653,7 +653,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) +int inia100_biosparam(Scsi_Disk * disk, struct block_device *dev, int *info_array) { ORC_HCS *pHcb; /* Point to Host adapter control block */ ORC_TCS *pTcb; diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h --- a/drivers/scsi/inia100.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/inia100.h Wed Jul 24 14:03:35 2002 @@ -83,7 +83,7 @@ extern int inia100_abort(Scsi_Cmnd *); extern int inia100_reset(Scsi_Cmnd *, unsigned int); -extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ +extern int inia100_biosparam(Scsi_Disk *, struct block_device *, int *); #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02c" diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/ips.c Wed Jul 24 14:03:35 2002 @@ -437,7 +437,7 @@ int ips_eh_abort(Scsi_Cmnd *); int ips_eh_reset(Scsi_Cmnd *); int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *)); -int ips_biosparam(Disk *, kdev_t, int *); +int ips_biosparam(Disk *, struct block_device *, int *); const char * ips_info(struct Scsi_Host *); void do_ipsintr(int, void *, struct pt_regs *); static int ips_hainit(ips_ha_t *); @@ -1853,7 +1853,7 @@ /* */ /****************************************************************************/ int -ips_biosparam(Disk *disk, kdev_t dev, int geom[]) { +ips_biosparam(Disk *disk, struct block_device *dev, int geom[]) { ips_ha_t *ha; int heads; int sectors; diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h --- a/drivers/scsi/ips.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/ips.h Wed Jul 24 14:03:36 2002 @@ -56,7 +56,7 @@ extern int ips_eh_abort(Scsi_Cmnd *); extern int ips_eh_reset(Scsi_Cmnd *); extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *)); - extern int ips_biosparam(Disk *, kdev_t, int *); + extern int ips_biosparam(Disk *, struct block_device *, int *); extern const char * ips_info(struct Scsi_Host *); extern void do_ips(int, void *, struct pt_regs *); diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/mac_esp.c Wed Jul 24 14:03:38 2002 @@ -360,14 +360,14 @@ } else { /* q950, 900, 700 */ quick = 1; - writel(0x1d1, 0xf9800024); + out_be32(0xf9800024, 0x1d1); esp->dregs = (void *) 0xf9800024; } } else { /* chipnum */ quick = 1; - writel(0x1d1, 0xf9800028); + out_be32(0xf9800028, 0x1d1); esp->dregs = (void *) 0xf9800028; } /* chipnum == 0 */ @@ -377,7 +377,7 @@ /* Set the command buffer */ esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = (volatile unsigned char*) cmd_buffer; + esp->esp_command_dvma = (__u32) cmd_buffer; /* various functions */ esp->dma_bytes_sent = &dma_bytes_sent; diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/megaraid.c Wed Jul 24 14:03:35 2002 @@ -4218,13 +4218,13 @@ * Return the disk geometry for a particular disk * Input: * Disk *disk - Disk geometry - * kdev_t dev - Device node + * struct block_device *dev - Device node * int *geom - Returns geometry fields * geom[0] = heads * geom[1] = sectors * geom[2] = cylinders *-------------------------------------------------------------*/ -int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom) +int megaraid_biosparam (Disk * disk, struct block_device *bdev, int *geom) { int heads, sectors, cylinders; mega_host_config *megaCfg; @@ -4251,7 +4251,7 @@ geom[2] = cylinders; } else { - if( mega_partsize(disk, dev, geom) == 0 ) return 0; + if( mega_partsize(disk, bdev, geom) == 0 ) return 0; printk(KERN_WARNING "megaraid: invalid partition on this disk on channel %d\n", @@ -4279,7 +4279,7 @@ } /* - * Function : static int mega_partsize(Disk * disk, kdev_t dev, int *geom) + * Function : static int mega_partsize(Disk * disk, struct block_device *bdev, int *geom) * * Purpose : to determine the BIOS mapping used to create the partition * table, storing the results (cyls, hds, and secs) in geom @@ -4289,7 +4289,7 @@ * Returns : -1 on failure, 0 on success. */ static int -mega_partsize(Disk * disk, kdev_t dev, int *geom) +mega_partsize(Disk * disk, struct block_device *bdev, int *geom) { struct partition *p, *largest = NULL; int i, largest_cyl; @@ -4297,7 +4297,7 @@ int capacity = disk->capacity; unsigned char *buf; - if (!(buf = scsi_bios_ptable(dev))) + if (!(buf = scsi_bios_ptable(bdev))) return -1; if( *(unsigned short *)(buf + 64) == 0xAA55 ) { @@ -4534,7 +4534,6 @@ unsigned int cmd, unsigned long arg) { int adapno; - kdev_t dev; u32 inlen; struct uioctl_t ioc; char *kvaddr = NULL; @@ -4560,8 +4559,6 @@ if (!inode) return -EINVAL; - - dev = inode->i_rdev; if (_IOC_TYPE (cmd) != MEGAIOC_MAGIC) return (-EINVAL); diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h --- a/drivers/scsi/megaraid.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/megaraid.h Wed Jul 24 14:03:38 2002 @@ -950,7 +950,7 @@ int megaraid_abort (Scsi_Cmnd *); int megaraid_reset (Scsi_Cmnd *, unsigned int); int megaraid_queue (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -int megaraid_biosparam (Disk *, kdev_t, int *); +int megaraid_biosparam (Disk *, struct block_device *, int *); int megaraid_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); @@ -998,7 +998,7 @@ static mega_ext_passthru* mega_prepare_extpassthru(mega_host_config *, mega_scb *, Scsi_Cmnd *); static void mega_enum_raid_scsi(mega_host_config *); -static int mega_partsize(Disk *, kdev_t, int *); +static int mega_partsize(Disk *, struct block_device *, int *); static void mega_get_boot_ldrv(mega_host_config *); static int mega_get_lun(mega_host_config *, Scsi_Cmnd *); static int mega_support_random_del(mega_host_config *); diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c --- a/drivers/scsi/mvme16x.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/mvme16x.c Wed Jul 24 14:03:37 2002 @@ -21,9 +21,9 @@ #include -extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, - unsigned long base, int io_port, int irq, int dma, - long long options, int clock); +extern int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, int chip, + unsigned long base, int io_port, int irq, int dma, + long long options, int clock); int mvme16x_scsi_detect(Scsi_Host_Template *tpnt) { diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c --- a/drivers/scsi/oktagon_esp.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/oktagon_esp.c Wed Jul 24 14:03:35 2002 @@ -554,8 +554,8 @@ void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp) { - sp->SCp.ptr = - sp->SCp.buffer->address; + sp->SCp.ptr = page_address(sp->SCp.buffer->page)+ + sp->SCp.buffer->offset; } void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp) @@ -568,7 +568,8 @@ void dma_advance_sg(Scsi_Cmnd *sp) { - sp->SCp.ptr = sp->SCp.buffer->address; + sp->SCp.ptr = page_address(sp->SCp.buffer->page)+ + sp->SCp.buffer->offset; } diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/pas16.c Wed Jul 24 14:03:35 2002 @@ -486,7 +486,7 @@ } /* - * Function : int pas16_biosparam(Disk *disk, kdev_t dev, int *ip) + * Function : int pas16_biosparam(Disk *disk, struct block_device *dev, int *ip) * * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for * the specified device / size. @@ -505,7 +505,7 @@ * and matching the H_C_S coordinates to what DOS uses. */ -int pas16_biosparam(Disk * disk, kdev_t dev, int * ip) +int pas16_biosparam(Disk * disk, struct block_device *dev, int * ip) { int size = disk->capacity; ip[0] = 64; diff -Nru a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h --- a/drivers/scsi/pas16.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/pas16.h Wed Jul 24 14:03:38 2002 @@ -115,7 +115,7 @@ #ifndef ASM int pas16_abort(Scsi_Cmnd *); -int pas16_biosparam(Disk *, kdev_t, int*); +int pas16_biosparam(Disk *, struct block_device *, int*); int pas16_detect(Scsi_Host_Template *); int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int pas16_reset(Scsi_Cmnd *, unsigned int); diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c --- a/drivers/scsi/pci2000.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/pci2000.c Wed Jul 24 14:03:38 2002 @@ -830,7 +830,7 @@ * Returns: zero. * ****************************************************************/ -int Pci2000_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[]) +int Pci2000_BiosParam (Scsi_Disk *disk, struct block_device *dev, int geom[]) { PADAPTER2000 padapter; diff -Nru a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h --- a/drivers/scsi/pci2000.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/pci2000.h Wed Jul 24 14:03:37 2002 @@ -22,7 +22,6 @@ #define _PCI2000_H #include -#include #ifndef PSI_EIDE_SCSIOP #define PSI_EIDE_SCSIOP 1 @@ -194,7 +193,7 @@ int Pci2000_Abort (Scsi_Cmnd *SCpnt); int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int flags); int Pci2000_Release (struct Scsi_Host *pshost); -int Pci2000_BiosParam (Disk *disk, kdev_t dev, int geom[]); +int Pci2000_BiosParam (Disk *disk, struct block_device *dev, int geom[]); #ifndef NULL #define NULL 0 diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c --- a/drivers/scsi/pci2220i.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/pci2220i.c Wed Jul 24 14:03:35 2002 @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -2903,7 +2902,7 @@ * Returns: zero. * ****************************************************************/ -int Pci2220i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[]) +int Pci2220i_BiosParam (Scsi_Disk *disk, struct block_device *dev, int geom[]) { POUR_DEVICE pdev; diff -Nru a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h --- a/drivers/scsi/pci2220i.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/pci2220i.h Wed Jul 24 14:03:38 2002 @@ -33,7 +33,7 @@ int Pci2220i_Abort (Scsi_Cmnd *SCpnt); int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags); int Pci2220i_Release (struct Scsi_Host *pshost); -int Pci2220i_BiosParam (Disk *disk, kdev_t dev, int geom[]); +int Pci2220i_BiosParam (Disk *disk, struct block_device *dev, int geom[]); #ifndef NULL #define NULL 0 diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c --- a/drivers/scsi/ppa.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/ppa.c Wed Jul 24 14:03:35 2002 @@ -998,7 +998,7 @@ * be done in sd.c. Even if it gets fixed there, this will still * work. */ -int ppa_biosparam(Disk * disk, kdev_t dev, int ip[]) +int ppa_biosparam(Disk * disk, struct block_device *dev, int ip[]) { ip[0] = 0x40; ip[1] = 0x20; diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h --- a/drivers/scsi/ppa.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/ppa.h Wed Jul 24 14:03:37 2002 @@ -170,7 +170,7 @@ int ppa_abort(Scsi_Cmnd *); int ppa_reset(Scsi_Cmnd *); int ppa_proc_info(char *, char **, off_t, int, int, int); -int ppa_biosparam(Disk *, kdev_t, int *); +int ppa_biosparam(Disk *, struct block_device *, int *); #define PPA { proc_name: "ppa", \ proc_info: ppa_proc_info, \ diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/psi240i.c Wed Jul 24 14:03:38 2002 @@ -703,7 +703,7 @@ * Returns: zero. * ****************************************************************/ -int Psi240i_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[]) +int Psi240i_BiosParam (Scsi_Disk *disk, struct block_device *dev, int geom[]) { POUR_DEVICE pdev; diff -Nru a/drivers/scsi/psi240i.h b/drivers/scsi/psi240i.h --- a/drivers/scsi/psi240i.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/psi240i.h Wed Jul 24 14:03:37 2002 @@ -28,7 +28,6 @@ #define _PSI240I_H #include -#include #ifndef PSI_EIDE_SCSIOP #define PSI_EIDE_SCSIOP 1 @@ -315,7 +314,7 @@ int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); int Psi240i_Abort (Scsi_Cmnd *SCpnt); int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags); -int Psi240i_BiosParam (Disk *disk, kdev_t dev, int geom[]); +int Psi240i_BiosParam (Disk *disk, struct block_device * dev, int geom[]); #ifndef NULL #define NULL 0 diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/qla1280.c Wed Jul 24 14:03:39 2002 @@ -1699,7 +1699,7 @@ * Return the disk geometry for the given SCSI device. **************************************************************************/ int -qla1280_biosparam(Disk * disk, kdev_t dev, int geom[]) +qla1280_biosparam(Disk * disk, struct block_device *dev, int geom[]) { int heads, sectors, cylinders; diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h --- a/drivers/scsi/qla1280.h Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/qla1280.h Wed Jul 24 14:03:39 2002 @@ -1313,7 +1313,7 @@ int qla1280_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); int qla1280_abort(Scsi_Cmnd *); int qla1280_reset(Scsi_Cmnd *, unsigned int); -int qla1280_biosparam(Disk *, kdev_t, int[]); +int qla1280_biosparam(Disk *, struct block_device *, int[]); void qla1280_intr_handler(int, void *, struct pt_regs *); void qla1280_setup(char *s, int *dummy); diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/qlogicfas.c Wed Jul 24 14:03:39 2002 @@ -651,7 +651,7 @@ /*----------------------------------------------------------------*/ /* return bios parameters */ -int qlogicfas_biosparam(Disk * disk, kdev_t dev, int ip[]) +int qlogicfas_biosparam(Disk * disk, struct block_device *dev, int ip[]) { /* This should mimic the DOS Qlogic driver's behavior exactly */ ip[0] = 0x40; diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h --- a/drivers/scsi/qlogicfas.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/qlogicfas.h Wed Jul 24 14:03:37 2002 @@ -7,7 +7,7 @@ int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int qlogicfas_abort(Scsi_Cmnd *); int qlogicfas_reset(Scsi_Cmnd *, unsigned int); -int qlogicfas_biosparam(Disk *, kdev_t, int[]); +int qlogicfas_biosparam(Disk *, struct block_device *, int[]); #ifndef NULL #define NULL (0) diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/qlogicfc.c Wed Jul 24 14:03:39 2002 @@ -1800,7 +1800,7 @@ } -int isp2x00_biosparam(Disk * disk, kdev_t n, int ip[]) +int isp2x00_biosparam(Disk * disk, struct block_device *n, int ip[]) { int size = disk->capacity; diff -Nru a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h --- a/drivers/scsi/qlogicfc.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/qlogicfc.h Wed Jul 24 14:03:37 2002 @@ -75,7 +75,7 @@ int isp2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int isp2x00_abort(Scsi_Cmnd *); int isp2x00_reset(Scsi_Cmnd *, unsigned int); -int isp2x00_biosparam(Disk *, kdev_t, int[]); +int isp2x00_biosparam(Disk *, struct block_device *, int[]); #ifndef NULL #define NULL (0) diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c --- a/drivers/scsi/qlogicisp.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/qlogicisp.c Wed Jul 24 14:03:38 2002 @@ -84,14 +84,11 @@ { \ unsigned long flags; \ \ - save_flags(flags); \ - cli(); \ trace.buf[trace.next].name = (w); \ trace.buf[trace.next].time = jiffies; \ trace.buf[trace.next].index = (i); \ trace.buf[trace.next].addr = (long) (a); \ trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \ - restore_flags(flags); \ } #else @@ -1240,7 +1237,7 @@ } -int isp1020_biosparam(Disk *disk, kdev_t n, int ip[]) +int isp1020_biosparam(Disk *disk, struct block_device *n, int ip[]) { int size = disk->capacity; @@ -1704,9 +1701,6 @@ ENTER("isp1020_load_parameters"); - save_flags(flags); - cli(); - hwrev = isp_inw(host, ISP_CFG0) & ISP_CFG0_HWMSK; isp_cfg1 = ISP_CFG1_F64 | ISP_CFG1_BENAB; if (hwrev == ISP_CFG0_1040A) { @@ -1724,7 +1718,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set initiator id failure\n"); return 1; } @@ -1736,7 +1729,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set retry count failure\n"); return 1; } @@ -1747,7 +1739,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : async data setup time failure\n"); return 1; } @@ -1759,7 +1750,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set active negation state failure\n"); return 1; } @@ -1771,7 +1761,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set pci control parameter failure\n"); return 1; } @@ -1782,7 +1771,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set tag age limit failure\n"); return 1; } @@ -1793,7 +1781,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set selection timeout failure\n"); return 1; } @@ -1812,7 +1799,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set target parameter failure\n"); return 1; } @@ -1827,7 +1813,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set device queue " "parameter failure\n"); return 1; @@ -1854,7 +1839,6 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set response queue failure\n"); return 1; } @@ -1879,12 +1863,9 @@ isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { - restore_flags(flags); printk("qlogicisp : set request queue failure\n"); return 1; } - - restore_flags(flags); LEAVE("isp1020_load_parameters"); diff -Nru a/drivers/scsi/qlogicisp.h b/drivers/scsi/qlogicisp.h --- a/drivers/scsi/qlogicisp.h Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/qlogicisp.h Wed Jul 24 14:03:35 2002 @@ -64,7 +64,7 @@ int isp1020_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int isp1020_abort(Scsi_Cmnd *); int isp1020_reset(Scsi_Cmnd *, unsigned int); -int isp1020_biosparam(Disk *, kdev_t, int[]); +int isp1020_biosparam(Disk *, struct block_device *, int[]); #ifndef NULL #define NULL (0) diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c --- a/drivers/scsi/qlogicpti.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/qlogicpti.c Wed Jul 24 14:03:36 2002 @@ -1456,7 +1456,7 @@ } while (dq != NULL); spin_unlock(qpti->qhost->host_lock); } - __restore_flags(flags); + local_irq_restore(flags); } int qlogicpti_abort(Scsi_Cmnd *Cmnd) diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/scsi.h Wed Jul 24 14:03:36 2002 @@ -627,6 +627,8 @@ int allow_revalidate; struct device sdev_driverfs_dev; }; +#define to_scsi_device(d) \ + container_of(d, struct scsi_device, sdev_driverfs_dev) /* diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/scsi_debug.c Wed Jul 24 14:03:38 2002 @@ -1008,7 +1008,7 @@ #endif } -static int scsi_debug_biosparam(Disk * disk, kdev_t dev, int *info) +static int scsi_debug_biosparam(Disk * disk, struct block_device *dev, int *info) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: biosparam\n"); diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h --- a/drivers/scsi/scsi_debug.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/scsi_debug.h Wed Jul 24 14:03:38 2002 @@ -1,13 +1,12 @@ #ifndef _SCSI_DEBUG_H #include -#include static int scsi_debug_detect(Scsi_Host_Template *); /* static int scsi_debug_command(Scsi_Cmnd *); */ static int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int scsi_debug_abort(Scsi_Cmnd *); -static int scsi_debug_biosparam(Disk *, kdev_t, int[]); +static int scsi_debug_biosparam(Disk *, struct block_device *, int[]); static int scsi_debug_bus_reset(Scsi_Cmnd *); static int scsi_debug_device_reset(Scsi_Cmnd *); static int scsi_debug_host_reset(Scsi_Cmnd *); diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/scsi_lib.c Wed Jul 24 14:03:38 2002 @@ -360,7 +360,7 @@ { request_queue_t *q = &SCpnt->device->request_queue; struct request *req = SCpnt->request; - int flags; + unsigned long flags; ASSERT_LOCK(q->queue_lock, 0); diff -Nru a/drivers/scsi/scsi_mid_low_api.txt b/drivers/scsi/scsi_mid_low_api.txt --- a/drivers/scsi/scsi_mid_low_api.txt Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/scsi_mid_low_api.txt Wed Jul 24 14:03:39 2002 @@ -85,7 +85,7 @@ * pre-initialized with made up values just in case this function * doesn't output anything. **/ - int bios_param(Scsi_Disk * sdkp, kdev_t dev, int params[3]); + int bios_param(Scsi_Disk * sdkp, struct block_device *bdev, int params[3]); /** diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/scsi_scan.c Wed Jul 24 14:03:39 2002 @@ -293,8 +293,7 @@ static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page, size_t count, loff_t off) { - struct scsi_device *SDpnt = list_entry(driverfs_dev, - struct scsi_device, sdev_driverfs_dev); + struct scsi_device *SDpnt = to_scsi_device(driverfs_dev); if ((SDpnt->type <= MAX_SCSI_DEVICE_CODE) && (scsi_device_types[(int)SDpnt->type] != NULL)) diff -Nru a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c --- a/drivers/scsi/scsicam.c Wed Jul 24 14:03:35 2002 +++ b/drivers/scsi/scsicam.c Wed Jul 24 14:03:35 2002 @@ -26,39 +26,25 @@ static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds, unsigned int *secs); -unsigned char *scsi_bios_ptable(kdev_t dev) +unsigned char *scsi_bios_ptable(struct block_device *dev) { - struct block_device *bdev; unsigned char *res = kmalloc(66, GFP_KERNEL); - kdev_t rdev = mk_kdev(major(dev), minor(dev) & ~0x0f); - if (res) { - struct buffer_head *bh; - int err; - - bdev = bdget(kdev_t_to_nr(rdev)); - if (!bdev) - goto fail; - err = blkdev_get(bdev, FMODE_READ, 0, BDEV_FILE); - if (err) - goto fail; - bh = __bread(bdev, 0, block_size(bdev)); - if (!bh) - goto fail2; - memcpy(res, bh->b_data + 0x1be, 66); - brelse(bh); - blkdev_put(bdev, BDEV_FILE); + struct block_device *bdev = dev->bd_contains; + struct buffer_head *bh = __bread(bdev, 0, block_size(bdev)); + if (bh) { + memcpy(res, bh->b_data + 0x1be, 66); + brelse(bh); + } else { + kfree(res); + res = NULL; + } } return res; -fail2: - blkdev_put(bdev, BDEV_FILE); -fail: - kfree(res); - return NULL; } /* - * Function : int scsicam_bios_param (Disk *disk, int dev, int *ip) + * Function : int scsicam_bios_param (Disk *disk, struct block_device *bdev, int *ip) * * Purpose : to determine the BIOS mapping used for a drive in a * SCSI-CAM system, storing the results in ip as required @@ -69,13 +55,13 @@ */ int scsicam_bios_param(Disk * disk, /* SCSI disk */ - kdev_t dev, /* Device major, minor */ + struct block_device *bdev, int *ip /* Heads, sectors, cylinders in that order */ ) { int ret_code; int size = disk->capacity; unsigned long temp_cyl; - unsigned char *p = scsi_bios_ptable(dev); + unsigned char *p = scsi_bios_ptable(bdev); if (!p) return -1; diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/sd.c Wed Jul 24 14:03:36 2002 @@ -233,33 +233,20 @@ or driver values */ if(host->hostt->bios_param != NULL) - host->hostt->bios_param(sdkp, dev, + host->hostt->bios_param(sdkp, inode->i_bdev, &diskinfo[0]); else - scsicam_bios_param(sdkp, dev, &diskinfo[0]); + scsicam_bios_param(sdkp, inode->i_bdev, &diskinfo[0]); if (put_user(diskinfo[0], &loc->heads) || put_user(diskinfo[1], &loc->sectors) || put_user(diskinfo[2], &loc->cylinders) || put_user((unsigned) - get_start_sect(inode->i_rdev), + get_start_sect(inode->i_bdev), (unsigned long *) &loc->start)) return -EFAULT; return 0; } - case BLKGETSIZE: - case BLKGETSIZE64: - case BLKROSET: - case BLKROGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - case BLKELVGET: - case BLKELVSET: - case BLKBSZGET: - case BLKBSZSET: - return blk_ioctl(inode->i_bdev, cmd, arg); - case BLKRRPART: /* Re-read partition tables */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -507,16 +494,6 @@ if (!scsi_block_when_processing_errors(sdp)) return -ENXIO; /* - * Make sure that only one process can do a check_change_disk at - * one time. This is also used to lock out further access when - * the partition table is being re-read. - */ - - while (sdp->busy) { - barrier(); - cpu_relax(); - } - /* * The following code can sleep. * Module unloading must be prevented */ @@ -527,9 +504,7 @@ sdp->access_count++; if (sdp->removable) { - sdp->allow_revalidate = 1; check_disk_change(inode->i_rdev); - sdp->allow_revalidate = 0; /* * If the drive is empty, just let the open fail. @@ -1464,9 +1439,10 @@ int revalidate_scsidisk(kdev_t dev, int maxusage) { int dsk_nr = DEVICE_NR(dev); - int res; Scsi_Disk * sdkp; Scsi_Device * sdp; + kdev_t device = mk_kdev(major(dev), minor(dev) & ~15); + int res; SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n", DEVICE_NR(dev))); @@ -1474,24 +1450,20 @@ if ((NULL == sdkp) || (NULL == (sdp = sdkp->device))) return -ENODEV; - if (sdp->busy || ((sdp->allow_revalidate == 0) && - (sdp->access_count > maxusage))) { - printk(KERN_WARNING "Device busy for revalidation " - "(access_count=%d)\n", sdp->access_count); - return -EBUSY; - } - sdp->busy = 1; + res = dev_lock_part(device); + if (res < 0) + return res; - res = wipe_partitions(dev); + res = wipe_partitions(device); if (res) goto leave; sd_init_onedisk(sdkp, dsk_nr); - grok_partitions(dev, sdkp->capacity); + grok_partitions(device, sdkp->capacity); leave: - sdp->busy = 0; + dev_unlock_part(device); return res; } diff -Nru a/drivers/scsi/sim710.h b/drivers/scsi/sim710.h --- a/drivers/scsi/sim710.h Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/sim710.h Wed Jul 24 14:03:38 2002 @@ -14,7 +14,7 @@ int sim710_bus_reset(Scsi_Cmnd * SCpnt); int sim710_dev_reset(Scsi_Cmnd * SCpnt); int sim710_host_reset(Scsi_Cmnd * SCpnt); -int sim710_biosparam(Disk *, kdev_t, int*); +int sim710_biosparam(Disk *, struct block_device *, int*); #ifdef MODULE int sim710_release(struct Scsi_Host *); #else diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/st.c Wed Jul 24 14:03:38 2002 @@ -12,13 +12,13 @@ Copyright 1992 - 2002 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Sat Jun 15 13:01:56 2002 by makisara + Last modified: Mon Jul 22 13:27:21 2002 by makisara Some small formal changes - aeb, 950809 Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20020615"; +static char *verstr = "20020722"; #include @@ -76,11 +76,11 @@ MODULE_LICENSE("GPL"); MODULE_PARM(buffer_kbs, "i"); -MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size (KB; 32)"); +MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size for fixed block mode (KB; 32)"); MODULE_PARM(write_threshold_kbs, "i"); MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)"); MODULE_PARM(max_sg_segs, "i"); -MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)"); +MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (64)"); #ifndef MODULE static struct st_dev_parm { @@ -139,25 +139,26 @@ static int modes_defined; -static ST_buffer *new_tape_buffer(int, int); +static ST_buffer *new_tape_buffer(int, int, int); static int enlarge_buffer(ST_buffer *, int, int); static void normalize_buffer(ST_buffer *); static int append_to_buffer(const char *, ST_buffer *, int); static int from_buffer(ST_buffer *, char *, int); +static void buf_to_sg(ST_buffer *, unsigned int); static int st_attach(Scsi_Device *); static int st_detect(Scsi_Device *); static void st_detach(Scsi_Device *); static struct Scsi_Device_Template st_template = { - module: THIS_MODULE, - name: "tape", - tag: "st", - scsi_type: TYPE_TAPE, - major: SCSI_TAPE_MAJOR, - detect: st_detect, - attach: st_attach, - detach: st_detach + .module = THIS_MODULE, + .name = "tape", + .tag = "st", + .scsi_type = TYPE_TAPE, + .major = SCSI_TAPE_MAJOR, + .detect = st_detect, + .attach = st_attach, + .detach = st_detach }; static int st_compression(Scsi_Tape *, int); @@ -361,12 +362,11 @@ if (SRpnt->sr_device->scsi_level <= SCSI_2) cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0; init_completion(&STp->wait); - SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ? - (STp->buffer)->use_sg : 0; + SRpnt->sr_use_sg = (bytes > (STp->buffer)->frp[0].length); if (SRpnt->sr_use_sg) { + buf_to_sg(STp->buffer, bytes); + SRpnt->sr_use_sg = (STp->buffer)->sg_segs; bp = (char *) &((STp->buffer)->sg[0]); - if ((STp->buffer)->sg_segs < SRpnt->sr_use_sg) - SRpnt->sr_use_sg = (STp->buffer)->sg_segs; } else bp = (STp->buffer)->b_data; SRpnt->sr_data_direction = direction; @@ -550,7 +550,6 @@ if (STp->ready != ST_READY) return 0; - STps = &(STp->ps[STp->partition]); if (STps->rw == ST_WRITING) /* Writing */ return flush_write_buffer(STp); @@ -1226,14 +1225,15 @@ ssize_t total; ssize_t i, do_count, blks, transfer; ssize_t retval; - int write_threshold; - int doing_write = 0; + int undone; + int async_write; unsigned char cmd[MAX_COMMAND_SIZE]; const char *b_point; Scsi_Request *SRpnt = NULL; Scsi_Tape *STp; ST_mode *STm; ST_partstat *STps; + ST_buffer *STbp; int dev = TAPE_NR(inode->i_rdev); read_lock(&st_dev_arr_lock); @@ -1286,12 +1286,13 @@ } } - if ((STp->buffer)->writing) { + STbp = STp->buffer; + if (STbp->writing) { write_behind_check(STp); - if ((STp->buffer)->syscall_result) { + if (STbp->syscall_result) { DEBC(printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n", - dev, (STp->buffer)->midlevel_result)); - if ((STp->buffer)->midlevel_result == INT_MAX) + dev, STbp->midlevel_result)); + if (STbp->midlevel_result == INT_MAX) STps->eof = ST_EOM_OK; else STps->eof = ST_EOM_ERROR; @@ -1299,6 +1300,7 @@ } if (STps->eof == ST_EOM_OK) { + STps->eof = ST_EOD_1; /* allow next write */ retval = (-ENOSPC); goto out; } @@ -1316,19 +1318,6 @@ goto out; } - if (!STm->do_buffer_writes) { -#if 0 - if (STp->block_size != 0 && (count % STp->block_size) != 0) { - retval = (-EINVAL); /* Write must be integral number of blocks */ - goto out; - } -#endif - write_threshold = 1; - } else - write_threshold = (STp->buffer)->buffer_blocks * STp->block_size; - if (!STm->do_async_writes) - write_threshold--; - total = count; memset(cmd, 0, MAX_COMMAND_SIZE); @@ -1338,29 +1327,44 @@ STps->rw = ST_WRITING; b_point = buf; - while ((STp->block_size == 0 && !STm->do_async_writes && count > 0) || - (STp->block_size != 0 && - (STp->buffer)->buffer_bytes + count > write_threshold)) { - doing_write = 1; + while (count > 0) { + if (STp->block_size == 0) do_count = count; else { - do_count = (STp->buffer)->buffer_blocks * STp->block_size - - (STp->buffer)->buffer_bytes; + do_count = STbp->buffer_blocks * STp->block_size - + STbp->buffer_bytes; if (do_count > count) do_count = count; } - i = append_to_buffer(b_point, STp->buffer, do_count); + i = append_to_buffer(b_point, STbp, do_count); if (i) { retval = i; goto out; } + count -= do_count; + filp->f_pos += do_count; + b_point += do_count; + + async_write = STm->do_async_writes && STps->eof < ST_EOM_OK; + if (STp->block_size != 0) + async_write &= count == 0 && + (!STm->do_buffer_writes || + STbp->buffer_bytes >= STp->write_threshold); + + if (STp->block_size != 0 && STm->do_buffer_writes && STps->eof < ST_EOM_OK && + STbp->buffer_bytes < STbp->buffer_size) { + STp->dirty = TRUE; + /* Don't write a buffer that is not full enough. */ + if (!async_write && count == 0) + break; + } if (STp->block_size == 0) blks = transfer = do_count; else { - blks = (STp->buffer)->buffer_bytes / + blks = STbp->buffer_bytes / STp->block_size; transfer = blks * STp->block_size; } @@ -1369,47 +1373,59 @@ cmd[4] = blks; SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + STp->timeout, MAX_WRITE_RETRIES, !async_write); if (!SRpnt) { - retval = (STp->buffer)->syscall_result; + retval = STbp->syscall_result; goto out; } + if (async_write) { + STbp->writing = transfer; + STp->dirty = !(STbp->writing == + STbp->buffer_bytes); + SRpnt = NULL; /* Prevent releasing this request! */ + DEB( STp->write_pending = 1; ) + break; + } - if ((STp->buffer)->syscall_result != 0) { + if (STbp->syscall_result != 0) { DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev)); if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && (SRpnt->sr_sense_buffer[2] & 0x40)) { if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0) - transfer = (SRpnt->sr_sense_buffer[3] << 24) | + undone = (SRpnt->sr_sense_buffer[3] << 24) | (SRpnt->sr_sense_buffer[4] << 16) | (SRpnt->sr_sense_buffer[5] << 8) | SRpnt->sr_sense_buffer[6]; else if (STp->block_size == 0 && (SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW) - transfer = do_count; + undone = do_count; else - transfer = 0; + undone = 0; if (STp->block_size != 0) - transfer *= STp->block_size; - if (transfer <= do_count) { - filp->f_pos += do_count - transfer; - count -= do_count - transfer; - if (STps->drv_block >= 0) { - if (STp->block_size == 0 && - transfer < do_count) - STps->drv_block++; - else if (STp->block_size != 0) - STps->drv_block += - (do_count - transfer) / - STp->block_size; - } + undone *= STp->block_size; + filp->f_pos -= undone; + if (undone <= do_count) { + /* Only data from this write is not written */ + count -= undone; + do_count -= undone; + if (STp->block_size) + blks = (transfer - undone) / STp->block_size; STps->eof = ST_EOM_OK; - retval = (-ENOSPC); /* EOM within current request */ + /* Continue in fixed block mode if all written + in this request but still something left to write + (retval left to zero) + */ + if (STp->block_size == 0 || + undone > 0 || count == 0) + retval = (-ENOSPC); /* EOM within current request */ DEBC(printk(ST_DEB_MSG "st%d: EOM with %d bytes unwritten.\n", dev, transfer)); } else { + /* Previously buffered data not written */ + count -= do_count; + blks = do_count = 0; STps->eof = ST_EOM_ERROR; STps->drv_block = (-1); /* Too cautious? */ retval = (-EIO); /* EOM for old data */ @@ -1418,80 +1434,33 @@ dev)); } } else { + filp->f_pos -= do_count; STps->drv_block = (-1); /* Too cautious? */ retval = (-EIO); } - scsi_release_request(SRpnt); - SRpnt = NULL; - (STp->buffer)->buffer_bytes = 0; - STp->dirty = 0; - if (count < total) - retval = total - count; - goto out; } - filp->f_pos += do_count; - b_point += do_count; - count -= do_count; + if (STps->drv_block >= 0) { if (STp->block_size == 0) - STps->drv_block++; + STps->drv_block += (do_count > 0); else STps->drv_block += blks; } - (STp->buffer)->buffer_bytes = 0; - STp->dirty = 0; - } - if (count != 0) { - STp->dirty = 1; - i = append_to_buffer(b_point, STp->buffer, count); - if (i) { - retval = i; - goto out; - } - filp->f_pos += count; - count = 0; - } - if (doing_write && (STp->buffer)->syscall_result != 0) { - retval = (STp->buffer)->syscall_result; - goto out; - } - - if (STm->do_async_writes && - (((STp->buffer)->buffer_bytes >= STp->write_threshold && - (STp->buffer)->buffer_bytes >= STp->block_size) || - STp->block_size == 0)) { - /* Schedule an asynchronous write */ - if (STp->block_size == 0) - (STp->buffer)->writing = (STp->buffer)->buffer_bytes; - else - (STp->buffer)->writing = ((STp->buffer)->buffer_bytes / - STp->block_size) * STp->block_size; - STp->dirty = !((STp->buffer)->writing == - (STp->buffer)->buffer_bytes); - - if (STp->block_size == 0) - blks = (STp->buffer)->writing; - else - blks = (STp->buffer)->writing / STp->block_size; - cmd[2] = blks >> 16; - cmd[3] = blks >> 8; - cmd[4] = blks; - DEB( STp->write_pending = 1; ) + STbp->buffer_bytes = 0; + STp->dirty = 0; - SRpnt = st_do_scsi(SRpnt, STp, cmd, (STp->buffer)->writing, - SCSI_DATA_WRITE, STp->timeout, - MAX_WRITE_RETRIES, FALSE); - if (SRpnt == NULL) { - retval = (STp->buffer)->syscall_result; + if (retval) { + if (count < total) + retval = total - count; goto out; } - SRpnt = NULL; /* Prevent releasing this request! */ - } - STps->at_sm &= (total == 0); - if (total > 0) + + if (STps->eof == ST_EOD_1) + STps->eof = ST_EOM_OK; + else STps->eof = ST_NOEOF; retval = total; @@ -2425,7 +2394,7 @@ if (STp->write_prot) return (-EACCES); cmd[0] = ERASE; - cmd[1] = 1; /* To the end of tape */ + cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */ if (STp->immediate) { cmd[1] |= 2; /* Don't wait for completion */ timeout = STp->timeout; @@ -3296,7 +3265,7 @@ /* Try to allocate a new tape buffer. Calling function must not hold dev_arr_lock. */ static ST_buffer * - new_tape_buffer(int from_initialization, int need_dma) + new_tape_buffer(int from_initialization, int need_dma, int max_sg) { int i, priority, got = 0, segs = 0; ST_buffer *tb; @@ -3306,26 +3275,29 @@ else priority = GFP_KERNEL; - i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist); + i = sizeof(ST_buffer) + (max_sg - 1) * sizeof(struct scatterlist) + + max_sg * sizeof(struct st_buf_fragment); tb = kmalloc(i, priority); if (!tb) { printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n"); return NULL; } - tb->sg_segs = tb->orig_sg_segs = segs; + memset(tb, 0, i); + tb->frp_segs = tb->orig_frp_segs = segs; + tb->use_sg = max_sg; if (segs > 0) tb->b_data = page_address(tb->sg[0].page); + tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg); tb->in_use = TRUE; tb->dma = need_dma; tb->buffer_size = got; - tb->writing = 0; return tb; } -/* Try to allocate a temporary enlarged tape buffer */ +/* Try to allocate enough space in the tape buffer */ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma) { int segs, nbr, max_segs, b_size, priority, order, got; @@ -3333,12 +3305,11 @@ if (new_size <= STbuffer->buffer_size) return TRUE; - normalize_buffer(STbuffer); + if (STbuffer->buffer_size <= PAGE_SIZE) + normalize_buffer(STbuffer); /* Avoid extra segment */ max_segs = STbuffer->use_sg; - if (max_segs > st_max_sg_segs) - max_segs = st_max_sg_segs; - nbr = max_segs - STbuffer->sg_segs; + nbr = max_segs - STbuffer->frp_segs; if (nbr <= 0) return FALSE; @@ -3350,12 +3321,10 @@ order++, b_size *= 2) ; /* empty */ - for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size; + for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size; segs < max_segs && got < new_size;) { - STbuffer->sg[segs].page = alloc_pages(priority, order); - /* printk("st: allocated %x, order %d\n", STbuffer->sg[segs].page, order); */ - STbuffer->sg[segs].offset = 0; - if (STbuffer->sg[segs].page == NULL) { + STbuffer->frp[segs].page = alloc_pages(priority, order); + if (STbuffer->frp[segs].page == NULL) { if (new_size - got <= (max_segs - segs) * b_size / 2) { b_size /= 2; /* Large enough for the rest of the buffers */ order--; @@ -3367,16 +3336,16 @@ normalize_buffer(STbuffer); return FALSE; } - STbuffer->sg[segs].length = b_size; - STbuffer->sg_segs += 1; + STbuffer->frp[segs].length = b_size; + STbuffer->frp_segs += 1; got += b_size; STbuffer->buffer_size = got; segs++; } - STbuffer->b_data = page_address(STbuffer->sg[0].page); + STbuffer->b_data = page_address(STbuffer->frp[0].page); DEBC(printk(ST_DEB_MSG "st: Succeeded to enlarge buffer at %p to %d bytes (segs %d->%d, %d).\n", - STbuffer, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size)); + STbuffer, got, STbuffer->orig_frp_segs, STbuffer->frp_segs, b_size)); return TRUE; } @@ -3385,22 +3354,20 @@ /* Release the extra buffer */ static void normalize_buffer(ST_buffer * STbuffer) { - int i, order, b_size; + int i, order; - for (i = STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) { - for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length; - order++, b_size *= 2) - ; /* empty */ - /* printk("st: freeing %x, order %d\n", STbuffer->sg[i].page, order); */ - __free_pages(STbuffer->sg[i].page, order); - STbuffer->buffer_size -= STbuffer->sg[i].length; + for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) { + order = get_order(STbuffer->frp[i].length); + __free_pages(STbuffer->frp[i].page, order); + STbuffer->buffer_size -= STbuffer->frp[i].length; } DEB( - if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs) - printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n", - STbuffer, STbuffer->buffer_size, STbuffer->sg_segs); + if (debugging && STbuffer->orig_frp_segs < STbuffer->frp_segs) + printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d->%d).\n", + STbuffer, STbuffer->buffer_size, STbuffer->frp_segs, STbuffer->orig_frp_segs); ) /* end DEB */ - STbuffer->sg_segs = STbuffer->orig_sg_segs; + STbuffer->frp_segs = STbuffer->orig_frp_segs; + STbuffer->frp_sg_current = 0; } @@ -3411,16 +3378,16 @@ int i, cnt, res, offset; for (i = 0, offset = st_bp->buffer_bytes; - i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++) - offset -= st_bp->sg[i].length; - if (i == st_bp->sg_segs) { /* Should never happen */ + i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++) + offset -= st_bp->frp[i].length; + if (i == st_bp->frp_segs) { /* Should never happen */ printk(KERN_WARNING "st: append_to_buffer offset overflow.\n"); return (-EIO); } - for (; i < st_bp->sg_segs && do_count > 0; i++) { - cnt = st_bp->sg[i].length - offset < do_count ? - st_bp->sg[i].length - offset : do_count; - res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt); + for (; i < st_bp->frp_segs && do_count > 0; i++) { + cnt = st_bp->frp[i].length - offset < do_count ? + st_bp->frp[i].length - offset : do_count; + res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt); if (res) return (-EFAULT); do_count -= cnt; @@ -3444,16 +3411,16 @@ int i, cnt, res, offset; for (i = 0, offset = st_bp->read_pointer; - i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++) - offset -= st_bp->sg[i].length; - if (i == st_bp->sg_segs) { /* Should never happen */ + i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++) + offset -= st_bp->frp[i].length; + if (i == st_bp->frp_segs) { /* Should never happen */ printk(KERN_WARNING "st: from_buffer offset overflow.\n"); return (-EIO); } - for (; i < st_bp->sg_segs && do_count > 0; i++) { - cnt = st_bp->sg[i].length - offset < do_count ? - st_bp->sg[i].length - offset : do_count; - res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt); + for (; i < st_bp->frp_segs && do_count > 0; i++) { + cnt = st_bp->frp[i].length - offset < do_count ? + st_bp->frp[i].length - offset : do_count; + res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt); if (res) return (-EFAULT); do_count -= cnt; @@ -3471,6 +3438,33 @@ } +/* Fill the s/g list up to the length required for this transfer */ +static void buf_to_sg(ST_buffer *STbp, unsigned int length) +{ + int i; + unsigned int count; + struct scatterlist *sg; + struct st_buf_fragment *frp; + + if (length == STbp->frp_sg_current) + return; /* work already done */ + + sg = &(STbp->sg[0]); + frp = STbp->frp; + for (i=count=0; count < length; i++) { + sg[i].page = frp[i].page; + if (length - count > frp[i].length) + sg[i].length = frp[i].length; + else + sg[i].length = length - count; + count += sg[i].length; + sg[i].offset = 0; + } + STbp->sg_segs = i; + STbp->frp_sg_current = length; +} + + /* Validate the options from command line or module parameters */ static void validate_options(void) { @@ -3587,7 +3581,10 @@ return 1; } - buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma); + i = SDp->host->sg_tablesize; + if (st_max_sg_segs < i) + i = st_max_sg_segs; + buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); return 1; @@ -3702,7 +3699,6 @@ else tpnt->tape_type = MT_ISSCSI2; - buffer->use_sg = tpnt->device->host->sg_tablesize; tpnt->buffer = buffer; tpnt->inited = 0; @@ -3714,7 +3710,7 @@ tpnt->use_pf = (SDp->scsi_level >= SCSI_2); tpnt->density = 0; tpnt->do_auto_lock = ST_AUTO_LOCK; - tpnt->can_bsr = ST_IN_FILE_POS; + tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */ tpnt->can_partitions = 0; tpnt->two_fm = ST_TWO_FM; tpnt->fast_mteom = ST_FAST_MTEOM; @@ -3802,7 +3798,7 @@ put_device(&tpnt->driverfs_dev_n[mode]); } if (tpnt->buffer) { - tpnt->buffer->orig_sg_segs = 0; + tpnt->buffer->orig_frp_segs = 0; normalize_buffer(tpnt->buffer); kfree(tpnt->buffer); } diff -Nru a/drivers/scsi/st.h b/drivers/scsi/st.h --- a/drivers/scsi/st.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/st.h Wed Jul 24 14:03:37 2002 @@ -21,12 +21,20 @@ int syscall_result; Scsi_Request *last_SRpnt; unsigned char *b_data; - unsigned short use_sg; /* zero or number of segments for this adapter */ - unsigned short sg_segs; /* total number of allocated segments */ - unsigned short orig_sg_segs; /* number of segments allocated at first try */ + unsigned short use_sg; /* zero or maximum number of s/g segments for this adapter */ + unsigned short sg_segs; /* number of segments in s/g list */ + unsigned short orig_frp_segs; /* number of segments allocated at first try */ + unsigned short frp_segs; /* number of buffer segments */ + unsigned int frp_sg_current; /* driver buffer length currently in s/g list */ + struct st_buf_fragment *frp; /* the allocated buffer fragment list */ struct scatterlist sg[1]; /* MUST BE last item */ } ST_buffer; +/* The tape buffer fragment descriptor */ +struct st_buf_fragment { + struct page *page; + unsigned int length; +}; /* The tape mode definition */ typedef struct { @@ -147,6 +155,9 @@ #define ST_EOD 7 /* EOD hit while reading => ST_EOD_1 => return zero => ST_EOD_2 => return zero => ST_EOD, return ENOSPC */ +/* When writing: ST_EOM_OK == early warning found, write OK + ST_EOD_1 == allow trying new write after early warning + ST_EOM_ERROR == early warning found, not able to write all */ /* Values of rw */ #define ST_IDLE 0 diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/sym53c416.c Wed Jul 24 14:03:36 2002 @@ -828,7 +828,7 @@ return SCSI_RESET_PENDING; } -static int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip) +static int sym53c416_bios_param(Disk *disk, struct block_device *dev, int *ip) { int size; diff -Nru a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h --- a/drivers/scsi/sym53c416.h Wed Jul 24 14:03:36 2002 +++ b/drivers/scsi/sym53c416.h Wed Jul 24 14:03:36 2002 @@ -27,7 +27,6 @@ #endif #include -#include #define SYM53C416_SCSI_ID 7 @@ -37,7 +36,7 @@ static int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int sym53c416_abort(Scsi_Cmnd *); static int sym53c416_reset(Scsi_Cmnd *, unsigned int); -static int sym53c416_bios_param(Disk *, kdev_t, int *); +static int sym53c416_bios_param(Disk *, struct block_device *, int *); static void sym53c416_setup(char *str, int *ints); #define SYM53C416 { \ diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/t128.c Wed Jul 24 14:03:39 2002 @@ -279,7 +279,7 @@ } /* - * Function : int t128_biosparam(Disk * disk, kdev_t dev, int *ip) + * Function : int t128_biosparam(Disk * disk, struct block_device *dev, int *ip) * * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for * the specified device / size. @@ -298,7 +298,7 @@ * and matching the H_C_S coordinates to what DOS uses. */ -int t128_biosparam(Disk * disk, kdev_t dev, int * ip) +int t128_biosparam(Disk * disk, struct block_device *dev, int * ip) { int size = disk->capacity; ip[0] = 64; diff -Nru a/drivers/scsi/t128.h b/drivers/scsi/t128.h --- a/drivers/scsi/t128.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/t128.h Wed Jul 24 14:03:37 2002 @@ -92,7 +92,7 @@ #ifndef ASM int t128_abort(Scsi_Cmnd *); -int t128_biosparam(Disk *, kdev_t, int*); +int t128_biosparam(Disk *, struct block_device *, int*); int t128_detect(Scsi_Host_Template *); int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int t128_reset(Scsi_Cmnd *, unsigned int reset_flags); diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/tmscsim.c Wed Jul 24 14:03:38 2002 @@ -1439,7 +1439,7 @@ * Note: * In contrary to other externally callable funcs (DC390_), we don't lock ***********************************************************************/ -int DC390_bios_param (Disk *disk, kdev_t devno, int geom[]) +int DC390_bios_param (Disk *disk, struct block_device *bdev, int geom[]) { int heads, sectors, cylinders; PACB pACB = (PACB) disk->device->host->hostdata; @@ -1447,7 +1447,7 @@ int size = disk->capacity; unsigned char *buf; - if ((buf = scsi_bios_ptable(devno))) + if ((buf = scsi_bios_ptable(bdev))) { /* try to infer mapping from partition table */ ret_code = partsize (buf, (unsigned long) size, (unsigned int *) geom + 2, @@ -1475,9 +1475,9 @@ return (0); } #else -int DC390_bios_param (Disk *disk, kdev_t devno, int geom[]) +int DC390_bios_param (Disk *disk, struct block_device *bdev, int geom[]) { - return scsicam_bios_param (disk, devno, geom); + return scsicam_bios_param (disk, bdev, geom); }; #endif @@ -2525,8 +2525,8 @@ if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, "")) goto einv2; \ else if (!p1) goto ok2 -#define SEARCH3(buffer, pos, &p0, var, txt, max, scale, ign) \ -if (dc390_search (&buffer, &pos, p0, &var, txt, max, scale, ign)) goto einv2; \ +#define SEARCH3(buffer, pos, p0, var, txt, max, scale, ign) \ +if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, ign)) goto einv2; \ else if (!p1) goto ok2 diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/u14-34f.c Wed Jul 24 14:03:37 2002 @@ -1452,7 +1452,7 @@ return do_reset(SCarg); } -int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { +int u14_34f_biosparam(Disk *disk, struct block_device *bdev, int *dkinfo) { unsigned int j = 0; int size = disk->capacity; @@ -1460,7 +1460,7 @@ dkinfo[1] = HD(j)->sectors; dkinfo[2] = size / (HD(j)->heads * HD(j)->sectors); - if (ext_tran && (scsicam_bios_param(disk, dev, dkinfo) < 0)) { + if (ext_tran && (scsicam_bios_param(disk, bdev, dkinfo) < 0)) { dkinfo[0] = 255; dkinfo[1] = 63; dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h --- a/drivers/scsi/u14-34f.h Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/u14-34f.h Wed Jul 24 14:03:39 2002 @@ -11,7 +11,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int u14_34f_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *); -int u14_34f_biosparam(Disk *, kdev_t, int *); +int u14_34f_biosparam(Disk *, struct block_device *, int *); #define U14_34F_VERSION "7.22.00" diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Wed Jul 24 14:03:38 2002 +++ b/drivers/scsi/ultrastor.c Wed Jul 24 14:03:38 2002 @@ -1020,7 +1020,7 @@ } -int ultrastor_biosparam(Disk * disk, kdev_t dev, int * dkinfo) +int ultrastor_biosparam(Disk * disk, struct block_device *dev, int * dkinfo) { int size = disk->capacity; unsigned int s = config.heads * config.sectors; diff -Nru a/drivers/scsi/ultrastor.h b/drivers/scsi/ultrastor.h --- a/drivers/scsi/ultrastor.h Wed Jul 24 14:03:37 2002 +++ b/drivers/scsi/ultrastor.h Wed Jul 24 14:03:37 2002 @@ -12,14 +12,13 @@ #ifndef _ULTRASTOR_H #define _ULTRASTOR_H -#include int ultrastor_detect(Scsi_Host_Template *); const char *ultrastor_info(struct Scsi_Host * shpnt); int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ultrastor_abort(Scsi_Cmnd *); int ultrastor_reset(Scsi_Cmnd *, unsigned int); -int ultrastor_biosparam(Disk *, kdev_t, int *); +int ultrastor_biosparam(Disk *, struct block_device *, int *); #define ULTRASTOR_14F_MAX_SG 16 diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/wd7000.c Wed Jul 24 14:03:39 2002 @@ -1706,9 +1706,9 @@ /* * This was borrowed directly from aha1542.c. (Zaga) */ -int wd7000_biosparam (Disk *disk, kdev_t dev, int *ip) +int wd7000_biosparam (Disk *disk, struct block_device *bdev, int *ip) { - dprintk("wd7000_biosparam: dev=%s, size=%d, ", kdevname(dev), + dprintk("wd7000_biosparam: dev=%s, size=%d, ", bdevname(bdev), disk->capacity); /* @@ -1727,7 +1727,7 @@ /* * try to figure out the geometry from the partition table */ - if ((scsicam_bios_param (disk, dev, info) < 0) || + if ((scsicam_bios_param (disk, bdev, info) < 0) || !(((info[0] == 64) && (info[1] == 32)) || ((info[0] == 255) && (info[1] == 63)))) { printk ("wd7000_biosparam: unable to verify geometry for disk with >1GB.\n" diff -Nru a/drivers/scsi/wd7000.h b/drivers/scsi/wd7000.h --- a/drivers/scsi/wd7000.h Wed Jul 24 14:03:39 2002 +++ b/drivers/scsi/wd7000.h Wed Jul 24 14:03:39 2002 @@ -12,7 +12,6 @@ */ #include -#include int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host); int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); @@ -21,7 +20,7 @@ int wd7000_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int wd7000_abort (Scsi_Cmnd *); int wd7000_reset (Scsi_Cmnd *, unsigned int); -int wd7000_biosparam (Disk *, kdev_t, int *); +int wd7000_biosparam (Disk *, struct block_device *, int *); #ifndef NULL #define NULL 0L diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/21285.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,540 @@ +/* + * linux/drivers/char/21285.c + * + * Driver for the serial port on the 21285 StrongArm-110 core logic chip. + * + * Based on drivers/char/serial.c + * + * $Id: 21285.c,v 1.34 2002/07/22 15:27:32 rmk Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define BAUD_BASE (mem_fclk_21285/64) + +#define SERIAL_21285_NAME "ttyFB" +#define SERIAL_21285_MAJOR 204 +#define SERIAL_21285_MINOR 4 + +#define RXSTAT_DUMMY_READ 0x80000000 +#define RXSTAT_FRAME (1 << 0) +#define RXSTAT_PARITY (1 << 1) +#define RXSTAT_OVERRUN (1 << 2) +#define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN) + +#define H_UBRLCR_BREAK (1 << 0) +#define H_UBRLCR_PARENB (1 << 1) +#define H_UBRLCR_PAREVN (1 << 2) +#define H_UBRLCR_STOPB (1 << 3) +#define H_UBRLCR_FIFO (1 << 4) + +static const char serial21285_name[] = "Footbridge UART"; + +#define tx_enabled(port) ((port)->unused[0]) +#define rx_enabled(port) ((port)->unused[1]) + +/* + * The documented expression for selecting the divisor is: + * BAUD_BASE / baud - 1 + * However, typically BAUD_BASE is not divisible by baud, so + * we want to select the divisor that gives us the minimum + * error. Therefore, we want: + * int(BAUD_BASE / baud - 0.5) -> + * int(BAUD_BASE / baud - (baud >> 1) / baud) -> + * int((BAUD_BASE - (baud >> 1)) / baud) + */ + +static void +serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + if (tx_enabled(port)) { + disable_irq(IRQ_CONTX); + tx_enabled(port) = 0; + } +} + +static void +serial21285_start_tx(struct uart_port *port, unsigned int tty_start) +{ + if (!tx_enabled(port)) { + enable_irq(IRQ_CONTX); + tx_enabled(port) = 1; + } +} + +static void serial21285_stop_rx(struct uart_port *port) +{ + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + if (rx_enabled(port)) { + disable_irq(IRQ_CONRX); + rx_enabled(port) = 0; + } + spin_unlock_irqrestore(&port->lock, flags); +} + +static void serial21285_enable_ms(struct uart_port *port) +{ +} + +static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + struct tty_struct *tty = port->info->tty; + unsigned int status, ch, rxs, max_count = 256; + + status = *CSR_UARTFLG; + while (!(status & 0x10) && max_count--) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty->flip.tqueue.routine((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + printk(KERN_WARNING "TTY_DONT_FLIP set\n"); + return; + } + } + + ch = *CSR_UARTDR; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + port->icount.rx++; + + rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ; + if (rxs & RXSTAT_ANYERR) { + if (rxs & RXSTAT_PARITY) + port->icount.parity++; + else if (rxs & RXSTAT_FRAME) + port->icount.frame++; + if (rxs & RXSTAT_OVERRUN) + port->icount.overrun++; + + rxs &= port->read_status_mask; + + if (rxs & RXSTAT_PARITY) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (rxs & RXSTAT_FRAME) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + + if ((rxs & port->ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((rxs & RXSTAT_OVERRUN) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character. + */ + *tty->flip.char_buf_ptr++ = 0; + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + tty->flip.count++; + } + status = *CSR_UARTFLG; + } + tty_flip_buffer_push(tty); +} + +static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + struct circ_buf *xmit = &port->info->xmit; + int count = 256; + + if (port->x_char) { + *CSR_UARTDR = port->x_char; + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + serial21285_stop_tx(port, 0); + return; + } + + do { + *CSR_UARTDR = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0 && !(*CSR_UARTFLG & 0x20)); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(port, EVT_WRITE_WAKEUP); + + if (uart_circ_empty(xmit)) + serial21285_stop_tx(port, 0); +} + +static unsigned int serial21285_tx_empty(struct uart_port *port) +{ + return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT; +} + +/* no modem control lines */ +static unsigned int serial21285_get_mctrl(struct uart_port *port) +{ + return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; +} + +static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static void serial21285_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int h_lcr; + + spin_lock_irqsave(&port->lock, flags); + h_lcr = *CSR_H_UBRLCR; + if (break_state) + h_lcr |= H_UBRLCR_BREAK; + else + h_lcr &= ~H_UBRLCR_BREAK; + *CSR_H_UBRLCR = h_lcr; + spin_unlock_irqrestore(&port->lock, flags); +} + +static int serial21285_startup(struct uart_port *port) +{ + int ret; + + tx_enabled(port) = 1; + rx_enabled(port) = 1; + + ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0, + serial21285_name, port); + if (ret == 0) { + ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0, + serial21285_name, port); + if (ret) + free_irq(IRQ_CONRX, port); + } + + return ret; +} + +static void serial21285_shutdown(struct uart_port *port) +{ + free_irq(IRQ_CONTX, port); + free_irq(IRQ_CONRX, port); +} + +static void +serial21285_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + unsigned int h_lcr; + + switch (cflag & CSIZE) { + case CS5: + h_lcr = 0x00; + break; + case CS6: + h_lcr = 0x20; + break; + case CS7: + h_lcr = 0x40; + break; + default: /* CS8 */ + h_lcr = 0x60; + break; + } + + if (cflag & CSTOPB) + h_lcr |= H_UBRLCR_STOPB; + if (cflag & PARENB) { + h_lcr |= H_UBRLCR_PARENB; + if (!(cflag & PARODD)) + h_lcr |= H_UBRLCR_PAREVN; + } + + if (port->fifosize) + h_lcr |= H_UBRLCR_FIFO; + + port->read_status_mask = RXSTAT_OVERRUN; + if (iflag & INPCK) + port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (iflag & IGNPAR) + port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY; + if (iflag & IGNBRK && iflag & IGNPAR) + port->ignore_status_mask |= RXSTAT_OVERRUN; + + /* + * Ignore all characters if CREAD is not set. + */ + if ((cflag & CREAD) == 0) + port->ignore_status_mask |= RXSTAT_DUMMY_READ; + + quot -= 1; + + *CSR_UARTCON = 0; + *CSR_L_UBRLCR = quot & 0xff; + *CSR_M_UBRLCR = (quot >> 8) & 0x0f; + *CSR_H_UBRLCR = h_lcr; + *CSR_UARTCON = 1; +} + +static const char *serial21285_type(struct uart_port *port) +{ + return port->type == PORT_21285 ? "DC21285" : NULL; +} + +static void serial21285_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, 32); +} + +static int serial21285_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, 32, serial21285_name) + != NULL ? 0 : -EBUSY; +} + +static void serial21285_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0) + port->type = PORT_21285; +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285) + ret = -EINVAL; + if (ser->irq != NO_IRQ) + ret = -EINVAL; + if (ser->baud_base != port->uartclk / 16) + ret = -EINVAL; + return ret; +} + +static struct uart_ops serial21285_ops = { + tx_empty: serial21285_tx_empty, + get_mctrl: serial21285_get_mctrl, + set_mctrl: serial21285_set_mctrl, + stop_tx: serial21285_stop_tx, + start_tx: serial21285_start_tx, + stop_rx: serial21285_stop_rx, + enable_ms: serial21285_enable_ms, + break_ctl: serial21285_break_ctl, + startup: serial21285_startup, + shutdown: serial21285_shutdown, + change_speed: serial21285_change_speed, + type: serial21285_type, + release_port: serial21285_release_port, + request_port: serial21285_request_port, + config_port: serial21285_config_port, + verify_port: serial21285_verify_port, +}; + +static struct uart_port serial21285_port = { + membase: 0, + mapbase: 0x42000160, + iotype: SERIAL_IO_MEM, + irq: NO_IRQ, + uartclk: 0, + fifosize: 16, + ops: &serial21285_ops, + flags: ASYNC_BOOT_AUTOCONF, +}; + +static void serial21285_setup_ports(void) +{ + serial21285_port.uartclk = mem_fclk_21285 / 4; +} + +#ifdef CONFIG_SERIAL_21285_CONSOLE + +static void +serial21285_console_write(struct console *co, const char *s, + unsigned int count) +{ + int i; + + for (i = 0; i < count; i++) { + while (*CSR_UARTFLG & 0x20) + barrier(); + *CSR_UARTDR = s[i]; + if (s[i] == '\n') { + while (*CSR_UARTFLG & 0x20) + barrier(); + *CSR_UARTDR = '\r'; + } + } +} + +static kdev_t serial21285_console_device(struct console *c) +{ + return mk_kdev(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); +} + +static void __init +serial21285_get_options(struct uart_port *port, int *baud, + int *parity, int *bits) +{ + if (*CSR_UARTCON == 1) { + unsigned int tmp; + + tmp = *CSR_H_UBRLCR; + switch (tmp & 0x60) { + case 0x00: + *bits = 5; + break; + case 0x20: + *bits = 6; + break; + case 0x40: + *bits = 7; + break; + default: + case 0x60: + *bits = 8; + break; + } + + if (tmp & H_UBRLCR_PARENB) { + *parity = 'o'; + if (tmp & H_UBRLCR_PAREVN) + *parity = 'e'; + } + + tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8); + + *baud = port->uartclk / (16 * (tmp + 1)); + } +} + +static int __init serial21285_console_setup(struct console *co, char *options) +{ + struct uart_port *port = &serial21285_port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (machine_is_personal_server()) + baud = 57600; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + serial21285_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +#ifdef CONFIG_SERIAL_21285_OLD +static struct console serial21285_old_cons = +{ + name: SERIAL_21285_OLD_NAME, + write: serial21285_console_write, + device: serial21285_console_device, + setup: serial21285_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; +#endif + +static struct console serial21285_console = +{ + name: SERIAL_21285_NAME, + write: serial21285_console_write, + device: serial21285_console_device, + setup: serial21285_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init rs285_console_init(void) +{ + serial21285_setup_ports(); + register_console(&serial21285_console); +} + +#define SERIAL_21285_CONSOLE &serial21285_console +#else +#define SERIAL_21285_CONSOLE NULL +#endif + +static struct uart_driver serial21285_reg = { + owner: THIS_MODULE, + driver_name: "ttyFB", +#ifdef CONFIG_DEVFS_FS + dev_name: "ttyFB%d", +#else + dev_name: "ttyFB", +#endif + major: SERIAL_21285_MAJOR, + minor: SERIAL_21285_MINOR, + nr: 1, + cons: SERIAL_21285_CONSOLE, +}; + +static int __init serial21285_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: 21285 driver $Revision: 1.34 $\n"); + + serial21285_setup_ports(); + + ret = uart_register_driver(&serial21285_reg); + if (ret == 0) + uart_add_one_port(&serial21285_reg, &serial21285_port); + + return ret; +} + +static void __exit serial21285_exit(void) +{ + uart_remove_one_port(&serial21285_reg, &serial21285_port); + uart_unregister_driver(&serial21285_reg); +} + +module_init(serial21285_init); +module_exit(serial21285_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.34 $"); diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,2001 @@ +/* + * linux/drivers/char/8250.c + * + * 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. + * + * $Id: 8250.c,v 1.84 2002/07/22 15:27:32 rmk Exp $ + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include "8250.h" + +/* + * Configuration: + * share_irqs - whether we pass SA_SHIRQ to request_irq(). This option + * is unsafe when used on edge-triggered interrupts. + */ +unsigned int share_irqs = SERIAL8250_SHARE_IRQS; + +/* + * 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) + +/* + * This converts from our new CONFIG_ symbols to the symbols + * that asm/serial.h expects. You _NEED_ to comment out the + * linux/config.h include contained inside asm/serial.h for + * this to work. + */ +#undef CONFIG_SERIAL_MANY_PORTS +#undef CONFIG_SERIAL_DETECT_IRQ +#undef CONFIG_SERIAL_MULTIPORT +#undef CONFIG_HUB6 + +#ifdef CONFIG_SERIAL_8250_DETECT_IRQ +#define CONFIG_SERIAL_DETECT_IRQ 1 +#endif +#ifdef CONFIG_SERIAL_8250_MULTIPORT +#define CONFIG_SERIAL_MULTIPORT 1 +#endif + +/* + * HUB6 is always on. This will be removed once the header + * files have been cleaned. + */ +#define CONFIG_HUB6 1 +#define CONFIG_SERIAL_MANY_PORTS 1 + +#include + +static struct old_serial_port old_serial_port[] = { + SERIAL_PORT_DFNS /* defined in asm/serial.h */ +}; + +#define UART_NR ARRAY_SIZE(old_serial_port) + +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE) + +#define PORT_RSA_MAX 4 +static int probe_rsa[PORT_RSA_MAX]; +static int force_rsa[PORT_RSA_MAX]; +#endif /* CONFIG_SERIAL_8250_RSA */ + +struct uart_8250_port { + struct uart_port port; + struct timer_list timer; /* "no irq" timer */ + struct list_head list; /* ports on this IRQ */ + unsigned char acr; + unsigned char ier; + unsigned char rev; + unsigned char lcr; + unsigned int 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 }, + { "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "Cirrus", 1, 0 }, + { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, + { "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, + { "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "Startech", 1, 0 }, + { "16C950/954", 128, UART_CLEAR_FIFO | UART_USE_FIFO }, + { "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, + { "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH }, + { "RSA", 2048, UART_CLEAR_FIFO | UART_USE_FIFO } +}; + +static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) +{ + offset <<= up->port.regshift; + + switch (up->port.iotype) { + case SERIAL_IO_HUB6: + outb(up->port.hub6 - 1 + offset, up->port.iobase); + return inb(up->port.iobase + 1); + + case SERIAL_IO_MEM: + return readb(up->port.membase + offset); + + default: + return inb(up->port.iobase + offset); + } +} + +static _INLINE_ void +serial_out(struct uart_8250_port *up, int offset, int value) +{ + offset <<= up->port.regshift; + + switch (up->port.iotype) { + case SERIAL_IO_HUB6: + outb(up->port.hub6 - 1 + offset, up->port.iobase); + outb(value, up->port.iobase + 1); + break; + + case SERIAL_IO_MEM: + writeb(value, up->port.membase + offset); + break; + + default: + outb(value, up->port.iobase + offset); + } +} + +/* + * We used to support using pause I/O for certain machines. We + * haven't supported this for a while, but just in case it's badly + * needed for certain old 386 machines, I've left these #define's + * in.... + */ +#define serial_inp(up, offset) serial_in(up, offset) +#define serial_outp(up, offset, value) serial_out(up, offset, value) + + +/* + * For the 16C950 + */ +static void serial_icr_write(struct uart_8250_port *up, int offset, int value) +{ + serial_out(up, UART_SCR, offset); + serial_out(up, UART_ICR, value); +} + +static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) +{ + unsigned int value; + + serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD); + serial_out(up, UART_SCR, offset); + value = serial_in(up, UART_ICR); + serial_icr_write(up, UART_ACR, up->acr); + + return value; +} + +#ifdef CONFIG_SERIAL_8250_RSA +/* + * Attempts to turn on the RSA FIFO. Returns zero on failure. + * We set the port uart clock rate if we succeed. + */ +static int __enable_rsa(struct uart_8250_port *up) +{ + unsigned char mode; + int result; + + mode = serial_inp(up, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + + if (!result) { + serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO); + mode = serial_inp(up, UART_RSA_MSR); + result = mode & UART_RSA_MSR_FIFO; + } + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16; + + return result; +} + +static void enable_rsa(struct uart_8250_port *up) +{ + if (up->port.type == PORT_RSA) { + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { + spin_lock_irq(&up->port.lock); + __enable_rsa(up); + spin_unlock_irq(&up->port.lock); + } + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) + serial_outp(up, UART_RSA_FRR, 0); + } +} + +/* + * Attempts to turn off the RSA FIFO. Returns zero on failure. + * It is unknown why interrupts were disabled in here. However, + * the caller is expected to preserve this behaviour by grabbing + * the spinlock before calling this function. + */ +static void disable_rsa(struct uart_8250_port *up) +{ + unsigned char mode; + int result; + + if (up->port.type == PORT_RSA && + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { + spin_lock_irq(&up->port.lock); + + mode = serial_inp(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + + if (!result) { + serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO); + mode = serial_inp(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); + } + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; + spin_unlock_irq(&up->port.lock); + } +} +#endif /* CONFIG_SERIAL_8250_RSA */ + +/* + * This is a quickie test to see how big the FIFO is. + * It doesn't work at all the time, more's the pity. + */ +static int size_fifo(struct uart_8250_port *up) +{ + unsigned char old_fcr, old_mcr, old_dll, old_dlm; + int count; + + old_fcr = serial_inp(up, UART_FCR); + old_mcr = serial_inp(up, UART_MCR); + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_outp(up, UART_MCR, UART_MCR_LOOP); + serial_outp(up, UART_LCR, UART_LCR_DLAB); + old_dll = serial_inp(up, UART_DLL); + old_dlm = serial_inp(up, UART_DLM); + serial_outp(up, UART_DLL, 0x01); + serial_outp(up, UART_DLM, 0x00); + serial_outp(up, UART_LCR, 0x03); + for (count = 0; count < 256; count++) + serial_outp(up, UART_TX, count); + mdelay(20);/* FIXME - schedule_timeout */ + for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) && + (count < 256); count++) + serial_inp(up, UART_RX); + serial_outp(up, UART_FCR, old_fcr); + serial_outp(up, UART_MCR, old_mcr); + serial_outp(up, UART_LCR, UART_LCR_DLAB); + serial_outp(up, UART_DLL, old_dll); + serial_outp(up, UART_DLM, old_dlm); + + return count; +} + +/* + * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's. + * When this function is called we know it is at least a StarTech + * 16650 V2, but it might be one of several StarTech UARTs, or one of + * its clones. (We treat the broken original StarTech 16650 V1 as a + * 16550, and why not? Startech doesn't seem to even acknowledge its + * existence.) + * + * What evil have men's minds wrought... + */ +static void +autoconfig_startech_uarts(struct uart_8250_port *up) +{ + unsigned char scratch, scratch2, scratch3, scratch4; + + /* + * First we check to see if it's an Oxford Semiconductor UART. + * + * If we have to do this here because some non-National + * Semiconductor clone chips lock up if you try writing to the + * LSR register (which serial_icr_read does) + */ + if (up->port.type == PORT_16550A) { + /* + * EFR [4] must be set else this test fails + * + * This shouldn't be necessary, but Mike Hudson + * (Exoray@isys.ca) claims that it's needed for 952 + * dual UART's (which are not recommended for new designs). + */ + up->acr = 0; + serial_out(up, UART_LCR, 0xBF); + serial_out(up, UART_EFR, 0x10); + serial_out(up, UART_LCR, 0x00); + /* Check for Oxford Semiconductor 16C950 */ + scratch = serial_icr_read(up, UART_ID1); + scratch2 = serial_icr_read(up, UART_ID2); + scratch3 = serial_icr_read(up, UART_ID3); + + if (scratch == 0x16 && scratch2 == 0xC9 && + (scratch3 == 0x50 || scratch3 == 0x52 || + scratch3 == 0x54)) { + up->port.type = PORT_16C950; + up->rev = serial_icr_read(up, UART_REV) | + (scratch3 << 8); + return; + } + } + + /* + * We check for a XR16C850 by setting DLL and DLM to 0, and then + * reading back DLL and DLM. The chip type depends on the DLM + * value read back: + * 0x10 - XR16C850 and the DLL contains the chip revision. + * 0x12 - XR16C2850. + * 0x14 - XR16C854. + */ + + /* Save the DLL and DLM */ + + serial_outp(up, UART_LCR, UART_LCR_DLAB); + scratch3 = serial_inp(up, UART_DLL); + scratch4 = serial_inp(up, UART_DLM); + + serial_outp(up, UART_DLL, 0); + serial_outp(up, UART_DLM, 0); + scratch2 = serial_inp(up, UART_DLL); + scratch = serial_inp(up, UART_DLM); + serial_outp(up, UART_LCR, 0); + + if (scratch == 0x10 || scratch == 0x12 || scratch == 0x14) { + if (scratch == 0x10) + up->rev = scratch2; + up->port.type = PORT_16850; + return; + } + + /* Restore the DLL and DLM */ + + serial_outp(up, UART_LCR, UART_LCR_DLAB); + serial_outp(up, UART_DLL, scratch3); + serial_outp(up, UART_DLM, scratch4); + serial_outp(up, UART_LCR, 0); + + /* + * We distinguish between the '654 and the '650 by counting + * how many bytes are in the FIFO. I'm using this for now, + * since that's the technique that was sent to me in the + * serial driver update, but I'm not convinced this works. + * I've had problems doing this in the past. -TYT + */ + if (size_fifo(up) == 64) + up->port.type = PORT_16654; + else + up->port.type = PORT_16650V2; +} + +/* + * 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 status1, status2, scratch, scratch2, scratch3; + unsigned char save_lcr, save_mcr; + unsigned long flags; + + DEBUG_AUTOCONF("Testing ttyS%d (0x%04x, 0x%08lx)...\n", + up->port.line, up->port.iobase, up->port.membase); + + if (!up->port.iobase && !up->port.membase) + return; + + /* + * 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(); + + if (!(up->port.flags & ASYNC_BUGGY_UART)) { + /* + * Do a simple existence test first; if we fail this, + * there's no point trying anything else. + * + * 0x80 is used as a nonsense port to prevent against + * false positives due to ISA bus float. The + * assumption is that 0x80 is a non-existent port; + * which should be safe since include/asm/io.h also + * makes this assumption. + */ + scratch = serial_inp(up, UART_IER); + serial_outp(up, UART_IER, 0); +#ifdef __i386__ + outb(0xff, 0x080); +#endif + scratch2 = serial_inp(up, UART_IER); + serial_outp(up, UART_IER, 0x0F); +#ifdef __i386__ + outb(0, 0x080); +#endif + scratch3 = serial_inp(up, UART_IER); + serial_outp(up, UART_IER, scratch); + if (scratch2 != 0 || scratch3 != 0x0F) { + /* + * We failed; there's nothing here + */ + DEBUG_AUTOCONF("serial: ttyS%d: simple autoconfig " + "failed (%02x, %02x)\n", + up->port.line, scratch2, scratch3); + goto out; + } + } + + save_mcr = serial_in(up, UART_MCR); + save_lcr = serial_in(up, UART_LCR); + + /* + * Check to see if a UART is really there. Certain broken + * internal modems based on the Rockwell chipset fail this + * test, because they apparently don't implement the loopback + * test mode. So this test is skipped on the COM 1 through + * COM 4 ports. This *should* be safe, since no board + * manufacturer would be stupid enough to design a board + * that conflicts with COM 1-4 --- we hope! + */ + if (!(up->port.flags & ASYNC_SKIP_TEST)) { + serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A); + status1 = serial_inp(up, UART_MSR) & 0xF0; + serial_outp(up, UART_MCR, save_mcr); + if (status1 != 0x90) { + DEBUG_AUTOCONF("serial: ttyS%d: no UART loopback " + "failed\n", up->port.line); + goto out; + } + } + serial_outp(up, UART_LCR, 0xBF); /* set up for StarTech test */ + serial_outp(up, UART_EFR, 0); /* EFR is the same as FCR */ + serial_outp(up, UART_LCR, 0); + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = serial_in(up, UART_IIR) >> 6; + switch (scratch) { + case 0: + up->port.type = PORT_16450; + break; + case 1: + up->port.type = PORT_UNKNOWN; + break; + case 2: + up->port.type = PORT_16550; + break; + case 3: + up->port.type = PORT_16550A; + break; + } + if (up->port.type == PORT_16550A) { + /* Check for Startech UART's */ + serial_outp(up, UART_LCR, UART_LCR_DLAB); + if (serial_in(up, UART_EFR) == 0) { + up->port.type = PORT_16650; + } else { + serial_outp(up, UART_LCR, 0xBF); + if (serial_in(up, UART_EFR) == 0) + autoconfig_startech_uarts(up); + } + } + if (up->port.type == PORT_16550A) { + /* Check for TI 16750 */ + serial_outp(up, UART_LCR, save_lcr | UART_LCR_DLAB); + serial_outp(up, UART_FCR, + UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + scratch = serial_in(up, UART_IIR) >> 5; + if (scratch == 7) { + /* + * If this is a 16750, and not a cheap UART + * clone, then it should only go into 64 byte + * mode if the UART_FCR7_64BYTE bit was set + * while UART_LCR_DLAB was latched. + */ + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_outp(up, UART_LCR, 0); + serial_outp(up, UART_FCR, + UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE); + scratch = serial_in(up, UART_IIR) >> 5; + if (scratch == 6) + up->port.type = PORT_16750; + } + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + } +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE) + /* + * Only probe for RSA ports if we got the region. + */ + if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) { + int i; + + for (i = 0 ; i < PORT_RSA_MAX ; ++i) { + if (!probe_rsa[i] && !force_rsa[i]) + break; + if (((probe_rsa[i] != up->port.iobase) || + check_region(up->port.iobase + UART_RSA_BASE, 16)) && + (force_rsa[i] != up->port.iobase)) + continue; + if (__enable_rsa(up)) { + up->port.type = PORT_RSA; + break; + } + } + } +#endif + serial_outp(up, UART_LCR, save_lcr); + if (up->port.type == PORT_16450) { + scratch = serial_in(up, UART_SCR); + serial_outp(up, UART_SCR, 0xa5); + status1 = serial_in(up, UART_SCR); + serial_outp(up, UART_SCR, 0x5a); + status2 = serial_in(up, UART_SCR); + serial_outp(up, UART_SCR, scratch); + + if ((status1 != 0xa5) || (status2 != 0x5a)) + up->port.type = PORT_8250; + } + + up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; + + if (up->port.type == PORT_UNKNOWN) + goto out; + + /* + * Reset the UART. + */ +#ifdef CONFIG_SERIAL_8250_RSA + if (up->port.type == PORT_RSA) + serial_outp(up, UART_RSA_FRR, 0); +#endif + 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); +#ifdef CONFIG_SERIAL_8250_RSA + if (up->port.iobase && up->port.type == PORT_RSA) { + release_region(up->port.iobase, 8); + request_region(up->port.iobase + UART_RSA_BASE, 16, + "serial_rsa"); + } +#endif +} + +static void autoconfig_irq(struct uart_8250_port *up) +{ + unsigned char save_mcr, save_ier; + unsigned char save_ICP = 0; + unsigned int ICP = 0; + unsigned long irqs; + int irq; + + if (up->port.flags & ASYNC_FOURPORT) { + ICP = (up->port.iobase & 0xfe0) | 0x1f; + save_ICP = inb_p(ICP); + outb_p(0x80, ICP); + (void) inb_p(ICP); + } + + /* forget possible initially masked and pending IRQ */ + probe_irq_off(probe_irq_on()); + save_mcr = serial_inp(up, UART_MCR); + save_ier = serial_inp(up, UART_IER); + serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2); + + irqs = probe_irq_on(); + serial_outp(up, UART_MCR, 0); + udelay (10); + if (up->port.flags & ASYNC_FOURPORT) { + serial_outp(up, UART_MCR, + UART_MCR_DTR | UART_MCR_RTS); + } else { + serial_outp(up, UART_MCR, + UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); + } + serial_outp(up, UART_IER, 0x0f); /* enable all intrs */ + (void)serial_inp(up, UART_LSR); + (void)serial_inp(up, UART_RX); + (void)serial_inp(up, UART_IIR); + (void)serial_inp(up, UART_MSR); + serial_outp(up, UART_TX, 0xFF); + udelay (20); + irq = probe_irq_off(irqs); + + serial_outp(up, UART_MCR, save_mcr); + serial_outp(up, UART_IER, save_ier); + + if (up->port.flags & ASYNC_FOURPORT) + outb_p(save_ICP, ICP); + + up->port.irq = (irq > 0) ? irq : 0; +} + +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); + } + if (up->port.type == PORT_16C950 && tty_stop) { + up->acr |= UART_ACR_TXDIS; + serial_icr_write(up, UART_ACR, up->acr); + } +} + +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); + } + /* + * We only do this from uart_start + */ + if (tty_start && up->port.type == PORT_16C950) { + up->acr &= ~UART_ACR_TXDIS; + serial_icr_write(up, UART_ACR, up->acr); + } +} + +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + up->ier &= ~UART_IER_RLSI; + up->port.read_status_mask &= ~UART_LSR_DR; + serial_out(up, UART_IER, up->ier); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static void serial8250_enable_ms(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + up->ier |= UART_IER_MSI; + serial_out(up, UART_IER, up->ier); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +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.tqueue.routine((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_8250_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_event(&up->port, EVT_WRITE_WAKEUP); + + 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 void 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"); +} + +/* + * 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 int serial_link_irq_chain(struct uart_8250_port *up) +{ + struct irq_info *i = irq_lists + up->port.irq; + int ret, irq_flags = share_irqs ? 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); + } + + 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); + + 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); +} + +/* + * 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 = ALPHA_KLUDGE_MCR; + + 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; + + 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; + + if (up->port.type == PORT_16C950) { + /* Wake up and initialize UART */ + up->acr = 0; + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, UART_EFR_ECB); + serial_outp(up, UART_IER, 0); + serial_outp(up, UART_LCR, 0); + serial_icr_write(up, UART_CSR, 0); /* Reset the UART */ + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, UART_EFR_ECB); + serial_outp(up, UART_LCR, 0); + } + +#ifdef CONFIG_SERIAL_8250_RSA + /* + * If this is an RSA port, see if we can kick it up to the + * higher speed clock. + */ + enable_rsa(up); +#endif + + /* + * Clear the FIFO buffers and disable them. + * (they will be reeanbled in change_speed()) + */ + 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 & ASYNC_BUGGY_UART) && + (serial_inp(up, UART_LSR) == 0xff)) { + printk("ttyS%d: LSR safety check engaged!\n", up->port.line); + return -ENODEV; + } + + /* + * If the "interrupt" for this port doesn't correspond with any + * hardware interrupt, we use a timer-based system. The original + * driver used to do this with IRQ0. + */ + if (!is_real_interrupt(up->port.irq)) { + unsigned int timeout = up->port.timeout; + + timeout = timeout > 6 ? (timeout / 2 - 2) : 1; + + up->timer.data = (unsigned long)up; + mod_timer(&up->timer, jiffies + timeout); + } else { + 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 & ASYNC_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 change_speed(), which will be occuring 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 & ASYNC_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 & ASYNC_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); + +#ifdef CONFIG_SERIAL_8250_RSA + /* + * Reset the RSA board back to 115kbps compat mode. + */ + disable_rsa(up); +#endif + + /* + * 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 void +serial8250_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned char cval, fcr = 0; + unsigned long flags; + + switch (cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + default: + case CS8: + cval = 0x03; + break; + } + + if (cflag & CSTOPB) + cval |= 0x04; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* + * 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 ((up->port.uartclk / quot) < (2400 * 16)) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; +#ifdef CONFIG_SERIAL_8250_RSA + else if (up->port.type == PORT_RSA) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; +#endif + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } + if (up->port.type == PORT_16750) + fcr |= UART_FCR7_64BYTE; + + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (iflag & IGNPAR) + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= UART_LSR_BI; + + /* + * Characteres to ignore + */ + up->port.ignore_status_mask = 0; + if (iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (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 (iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_OE; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((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, cflag)) + up->ier |= UART_IER_MSI; + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + serial_out(up, UART_IER, up->ier); + + if (uart_config[up->port.type].flags & UART_STARTECH) { + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, cflag & CRTSCTS ? UART_EFR_CTS :0); + } + serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_outp(up, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_outp(up, UART_DLM, quot >> 8); /* MS of divisor */ + if (up->port.type == PORT_16750) + serial_outp(up, UART_FCR, fcr); /* set fcr */ + serial_outp(up, UART_LCR, cval); /* reset DLAB */ + 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 (uart_config[up->port.type].flags & UART_STARTECH) { + /* Arrange to enter sleep mode */ + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, UART_EFR_ECB); + serial_outp(up, UART_LCR, 0); + serial_outp(up, UART_IER, UART_IERX_SLEEP); + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, 0); + serial_outp(up, UART_LCR, 0); + } + if (up->port.type == PORT_16750) { + /* Arrange to enter sleep mode */ + serial_outp(up, UART_IER, UART_IERX_SLEEP); + } + + if (up->pm) + up->pm(port, state, oldstate); + } else { + /* wake */ + if (uart_config[up->port.type].flags & UART_STARTECH) { + /* Wake up UART */ + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, UART_EFR_ECB); + /* + * Turn off LCR == 0xBF so we actually set the IER + * register on the XR16C850 + */ + serial_outp(up, UART_LCR, 0); + serial_outp(up, UART_IER, 0); + /* + * Now reset LCR so we can turn off the ECB bit + */ + serial_outp(up, UART_LCR, 0xBF); + serial_outp(up, UART_EFR, 0); + /* + * For a XR16C850, we need to set the trigger levels + */ + if (up->port.type == PORT_16850) { + unsigned char fctr; + + fctr = serial_inp(up, UART_FCTR) & + ~(UART_FCTR_RX | UART_FCTR_TX); + serial_outp(up, UART_FCTR, fctr | + UART_FCTR_TRGD | + UART_FCTR_RX); + serial_outp(up, UART_TRG, UART_TRG_96); + serial_outp(up, UART_FCTR, fctr | + UART_FCTR_TRGD | + UART_FCTR_TX); + serial_outp(up, UART_TRG, UART_TRG_96); + } + serial_outp(up, UART_LCR, 0); + } + + if (up->port.type == PORT_16750) { + /* Wake up UART */ + serial_outp(up, UART_IER, 0); + } + + 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 int +serial8250_request_rsa_resource(struct uart_8250_port *up, struct resource **res) +{ + unsigned int size = 8 << up->port.regshift; + unsigned long start; + int ret = 0; + + switch (up->port.iotype) { + case SERIAL_IO_MEM: + if (up->port.mapbase) { + start = up->port.mapbase; + start += UART_RSA_BASE << up->port.regshift; + *res = request_mem_region(start, size, "serial-rsa"); + if (!*res) + ret = -EBUSY; + } + break; + + case SERIAL_IO_HUB6: + case SERIAL_IO_PORT: + start = up->port.iobase; + start += UART_RSA_BASE << up->port.regshift; + *res = request_region(start, size, "serial-rsa"); + 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; + + if (up->port.type == PORT_RSA) { + offset = UART_RSA_BASE << up->port.regshift; + size = 8; + } + + 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 = -EBUSY; + + if (up->port.type == PORT_RSA) { + ret = serial8250_request_rsa_resource(up, &res_rsa); + if (ret) + return ret; + } + + ret = serial8250_request_std_resource(up, &res); + + /* + * If we have a mapbase, then request that as well. + */ + if (res != NULL && up->port.iotype == SERIAL_IO_MEM && + up->port.mapbase) { + int size = res->end - res->start + 1; + + up->port.membase = ioremap(up->port.mapbase, size); + if (!up->port.membase) + ret = -ENOMEM; + } + + if (ret) { + 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; + int ret; + +#ifdef CONFIG_MCA + /* + * Don't probe for MCA ports on non-MCA machines. + */ + if (up->port.flags & ASYNC_BOOT_ONLYMCA && !MCA_bus) + return; +#endif + + /* + * Find the region that we can probe for. This in turn + * tells us whether we can probe for the type of port. + */ + ret = serial8250_request_std_resource(up, &res_std); + if (ret) + return; + + ret = serial8250_request_rsa_resource(up, &res_rsa); + if (ret) + probeflags &= ~PROBE_RSA; + + if (flags & UART_CONFIG_TYPE) + autoconfig(up, probeflags); + if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) + autoconfig_irq(up); + + /* + * 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) + 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, + change_speed: serial8250_change_speed, + 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) +{ + static int first = 1; + int i; + + if (!first) + return; + first = 0; + + for (i = 0; i < ARRAY_SIZE(old_serial_port); i++) { + serial8250_ports[i].port.iobase = old_serial_port[i].port; + serial8250_ports[i].port.irq = irq_cannonicalize(old_serial_port[i].irq); + serial8250_ports[i].port.uartclk = old_serial_port[i].base_baud * 16; + serial8250_ports[i].port.flags = old_serial_port[i].flags; + serial8250_ports[i].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++) { + serial8250_ports[i].port.line = i; + serial8250_ports[i].port.ops = &serial8250_pops; + init_timer(&serial8250_ports[i].timer); + serial8250_ports[i].timer.function = serial8250_timeout; + uart_add_one_port(drv, &serial8250_ports[i].port); + } +} + +#ifdef CONFIG_SERIAL_8250_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 & ASYNC_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 kdev_t serial8250_console_device(struct console *co) +{ + return mk_kdev(TTY_MAJOR, 64 + co->index); +} + +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); +} + +static struct console serial8250_console = { + name: "ttyS", + write: serial8250_console_write, + device: serial8250_console_device, + setup: serial8250_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init serial8250_console_init(void) +{ + serial8250_isa_init_ports(); + register_console(&serial8250_console); +} + +#define SERIAL8250_CONSOLE &serial8250_console +#else +#define SERIAL8250_CONSOLE NULL +#endif + +static struct uart_driver serial8250_reg = { + owner: THIS_MODULE, + driver_name: "serial", +#ifdef CONFIG_DEVFS_FS + dev_name: "tts/%d", +#else + dev_name: "ttyS", +#endif + 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 | ASYNC_BOOT_AUTOCONF; + port.line = line; + + if (HIGH_BITS_OFFSET) + port.iobase |= 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 neccessary 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 serial_struct *req) +{ + __register_serial(req, req->line); + 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; + } +} + +static int __init serial8250_init(void) +{ + int ret, i; + + printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.84 $ " + "IRQ sharing %sabled\n", share_irqs ? "en" : "dis"); + + for (i = 0; i < NR_IRQS; i++) + spin_lock_init(&irq_lists[i].lock); + + ret = uart_register_driver(&serial8250_reg); + if (ret) + return ret; + + serial8250_register_ports(&serial8250_reg); + return 0; +} + +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); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.84 $"); + +MODULE_PARM(share_irqs, "i"); +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" + " (unsafe)"); + +#if defined(CONFIG_SERIAL_8250_RSA) && defined(MODULE) +MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); +MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i"); +MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA"); +#endif diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250.h Wed Jul 24 14:03:39 2002 @@ -0,0 +1,60 @@ +/* + * linux/drivers/char/8250.h + * + * 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. + * + * $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $ + */ + +#include + +struct serial8250_probe { + struct module *owner; + int (*pci_init_one)(struct pci_dev *dev); + void (*pci_remove_one)(struct pci_dev *dev); + void (*pnp_init)(void); +}; + +int serial8250_register_probe(struct serial8250_probe *probe); +void serial8250_unregister_probe(struct serial8250_probe *probe); +void serial8250_get_irq_map(unsigned int *map); + +struct old_serial_port { + unsigned int uart; + unsigned int base_baud; + unsigned int port; + unsigned int irq; + unsigned int flags; +}; + +#undef SERIAL_DEBUG_PCI + +#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) +#define SERIAL_INLINE +#endif + +#ifdef SERIAL_INLINE +#define _INLINE_ inline +#else +#define _INLINE_ +#endif + +#define PROBE_RSA (1 << 0) +#define PROBE_ANY (~0) + +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + +#ifdef CONFIG_SERIAL_8250_SHARE_IRQ +#define SERIAL8250_SHARE_IRQS 1 +#else +#define SERIAL8250_SHARE_IRQS 0 +#endif diff -Nru a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250_cs.c Wed Jul 24 14:03:38 2002 @@ -0,0 +1,719 @@ +/*====================================================================== + + A driver for PCMCIA serial devices + + serial_cs.c 1.123 2000/08/24 18:46:38 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 = "serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +/* Enable the speaker? */ +static int do_sound = 1; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(do_sound, "i"); + +/*====================================================================*/ + +/* Table of multi-port card ID's */ + +struct multi_id { + u_short manfid; + u_short prodid; + int multi; /* 1 = multifunction, > 1 = # ports */ +}; + +static struct multi_id multi_id[] = { + { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, + { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, + { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, + { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } +}; +#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) + +typedef struct serial_info { + dev_link_t link; + int ndev; + int multi; + int slave; + int manfid; + dev_node_t node[4]; + int line[4]; + struct tq_struct remove; +} serial_info_t; + +static void serial_config(dev_link_t * link); +static int serial_event(event_t event, int priority, + event_callback_args_t * args); + +static dev_info_t dev_info = "serial_cs"; + +static dev_link_t *serial_attach(void); +static void serial_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +/*====================================================================*/ + +static void +cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + After a card is removed, do_serial_release() will unregister + the serial device(s), and release the PCMCIA configuration. + +======================================================================*/ + +/* + * This always runs in process context. + */ +static void do_serial_release(void *arg) +{ + struct serial_info *info = arg; + int i; + + DEBUG(0, "serial_release(0x%p)\n", &info->link); + + /* + * Recheck to see if the device is still configured. + */ + if (info->link.state & DEV_CONFIG) { + for (i = 0; i < info->ndev; i++) + unregister_serial(info->line[i]); + + info->link.dev = NULL; + + if (!info->slave) { + CardServices(ReleaseConfiguration, info->link.handle); + CardServices(ReleaseIO, info->link.handle, &info->link.io); + CardServices(ReleaseIRQ, info->link.handle, &info->link.irq); + } + + info->link.state &= ~DEV_CONFIG; + } +} + +/* + * This may be called from IRQ context. + */ +static void serial_remove(dev_link_t *link) +{ + struct serial_info *info = link->priv; + + link->state &= ~DEV_PRESENT; + + /* + * FIXME: Since the card has probably been removed, + * we should call into the serial layer and hang up + * the ports on the card immediately. + */ + + if (link->state & DEV_CONFIG) + schedule_task(&info->remove); +} + +/*====================================================================== + + serial_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *serial_attach(void) +{ + serial_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "serial_attach()\n"); + + /* Create new serial device */ + info = kmalloc(sizeof (*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof (*info)); + link = &info->link; + link->priv = info; + + INIT_TQUEUE(&info->remove, do_serial_release, info); + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_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->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + if (do_sound) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + 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 = &serial_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + serial_detach(link); + return NULL; + } + + return link; +} + +/*====================================================================== + + 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 serial_detach(dev_link_t * link) +{ + serial_info_t *info = link->priv; + dev_link_t **linkp; + int ret; + + DEBUG(0, "serial_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + + /* + * Ensure any outstanding scheduled tasks are completed. + */ + flush_scheduled_tasks(); + + /* + * Ensure that the ports have been released. + */ + do_serial_release(info); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree(info); +} + +/*====================================================================*/ + +static int setup_serial(serial_info_t * info, ioaddr_t port, int irq) +{ + struct serial_struct serial; + int line; + + memset(&serial, 0, sizeof (serial)); + serial.port = port; + serial.irq = irq; + serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," + " irq %d failed\n", (u_long) serial.port, serial.irq); + return -1; + } + + info->line[info->ndev] = line; + sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); + info->node[info->ndev].major = TTY_MAJOR; + info->node[info->ndev].minor = 0x40 + line; + if (info->ndev > 0) + info->node[info->ndev - 1].next = &info->node[info->ndev]; + info->ndev++; + + return 0; +} + +/*====================================================================*/ + +static int +get_tuple(int fn, client_handle_t handle, tuple_t * tuple, cisparse_t * parse) +{ + int i; + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + return CardServices(ParseTuple, handle, tuple, parse); +} + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +/*====================================================================*/ + +static int simple_config(dev_link_t * link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j, try; + + /* If the card is already configured, look up the port and irq */ + i = CardServices(GetConfigurationInfo, handle, &config); + if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { + ioaddr_t port = 0; + if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { + port = config.BasePort2; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (config.NumPorts1 == 0x40)) { + port = config.BasePort1 + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(info, port, config.AssignedIRQ); + } + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + /* Two tries: without IO aliases, then with aliases */ + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) + goto next_entry; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && + (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = + CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + next_entry: + i = next_tuple(handle, &tuple, &parse); + } + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && + ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + link->io.IOAddrLines = base[j] ? 16 : 3; + i = CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + + found_port: + if (i != CS_SUCCESS) { + printk(KERN_NOTICE + "serial_cs: no usable port range found, giving up\n"); + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + if (info->multi && (info->manfid == MANFID_3COM)) + link->conf.ConfigIndex &= ~(0x08); + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); +} + +static int multi_config(dev_link_t * link) +{ + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, base2 = 0; + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* First, look for a generic full-sized window */ + link->io.NumPorts1 = info->multi * 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + /* The quad port cards have bad CIS's, so just look for a + window larger than 8 ports and assume it will be right */ + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && + (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = + cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort1 + 8; + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + /* If that didn't work, look for two windows */ + if (i != CS_SUCCESS) { + link->io.NumPorts1 = link->io.NumPorts2 = 8; + info->multi = 2; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.BasePort2 = cf->io.win[1].base; + link->io.IOAddrLines = + cf->io.flags & CISTPL_IO_LINES_MASK; + i = + CardServices(RequestIO, link->handle, + &link->io); + base2 = link->io.BasePort2; + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + printk(KERN_NOTICE + "serial_cs: no usable port range found, giving up\n"); + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + /* Socket Dual IO: this enables irq's for second port */ + if (info->multi && (info->manfid == MANFID_SOCKET)) { + link->conf.Present |= PRESENT_EXT_STATUS; + link->conf.ExtStatus = ESR_REQ_ATTN_ENA; + } + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + /* The Nokia cards are not really multiport cards */ + if (info->manfid == MANFID_NOKIA) + return 0; + for (i = 0; i < info->multi - 1; i++) + setup_serial(info, base2 + (8 * i), link->irq.AssignedIRQ); + + return 0; +} + +/*====================================================================== + + serial_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + serial device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +void serial_config(dev_link_t * link) +{ + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, last_ret, last_fn; + + DEBUG(0, "serial_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != 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; + + /* Is this a compliant multifunction card? */ + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); + + /* Is this a multiport card? */ + tuple.DesiredTuple = CISTPL_MANFID; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + info->manfid = le16_to_cpu(buf[0]); + for (i = 0; i < MULTI_COUNT; i++) + if ((info->manfid == multi_id[i].manfid) && + (le16_to_cpu(buf[1]) == multi_id[i].prodid)) + break; + if (i < MULTI_COUNT) + info->multi = multi_id[i].multi; + } + + /* Another check for dual-serial cards: look for either serial or + multifunction cards that ask for appropriate IO port ranges */ + tuple.DesiredTuple = CISTPL_FUNCID; + if ((info->multi == 0) && + ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || + (parse.funcid.func == CISTPL_FUNCID_MULTI) || + (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) + info->multi = cf->io.win[0].len >> 3; + if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)) + info->multi = 2; + } + } + + if (info->multi > 1) + multi_config(link); + else + simple_config(link); + + if (info->ndev == 0) + goto failed; + + if (info->manfid == MANFID_IBM) { + conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + reg.Action = CS_WRITE; + reg.Value = reg.Value | 1; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + } + + link->dev = &info->node[0]; + link->state &= ~DEV_CONFIG_PENDING; + return; + + cs_failed: + cs_error(link->handle, last_fn, last_ret); + failed: + do_serial_release(info); +} + +/*====================================================================== + + 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 serial drivers from + talking to the ports. + +======================================================================*/ + +static int +serial_event(event_t event, int priority, event_callback_args_t * args) +{ + dev_link_t *link = args->client_data; + serial_info_t *info = link->priv; + + DEBUG(1, "serial_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + serial_remove(link); + break; + + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + serial_config(link); + break; + + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if ((link->state & DEV_CONFIG) && !info->slave) + CardServices(ReleaseConfiguration, link->handle); + break; + + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link) && !info->slave) + CardServices(RequestConfiguration, link->handle, + &link->conf); + break; + } + return 0; +} + +/*====================================================================*/ + +static int __init init_serial_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "serial_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &serial_attach, &serial_detach); + return 0; +} + +static void __exit exit_serial_cs(void) +{ + DEBUG(0, "serial_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + serial_detach(dev_list); +} + +module_init(init_serial_cs); +module_exit(exit_serial_cs); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250_pci.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,1138 @@ +/* + * linux/drivers/char/8250_pci.c + * + * Probe module for 8250/16550-type PCI serial ports. + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2001 Russell King, 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. + * + * $Id: 8250_pci.c,v 1.19 2002/07/21 21:32:30 rmk Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* 2.4.6 compatibility cruft - to be removed with the old serial.c code */ +#define pci_board __pci_board +#include +#undef pci_board + +#include +#include +#include + +#include "8250.h" + + +#ifndef IS_PCI_REGION_IOPORT +#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ + IORESOURCE_IO) +#endif +#ifndef IS_PCI_REGION_IOMEM +#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ + IORESOURCE_MEM) +#endif +#ifndef PCI_IRQ_RESOURCE +#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) +#endif + +#ifndef pci_get_subvendor +#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) +#define pci_get_subdevice(dev) ((dev)->subsystem_device) +#endif + +struct serial_private { + unsigned int nr; + struct pci_board *board; + int line[0]; +}; + +struct pci_board { + int flags; + int num_ports; + int base_baud; + int uart_offset; + int reg_shift; + int (*init_fn)(struct pci_dev *dev, struct pci_board *board, + int enable); + int first_uart_offset; +}; + +static int +get_pci_port(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned long port; + int base_idx; + int max_port; + int offset; + + base_idx = SPCI_FL_GET_BASE(board->flags); + if (board->flags & SPCI_FL_BASE_TABLE) + base_idx += idx; + + if (board->flags & SPCI_FL_REGION_SZ_CAP) { + max_port = pci_resource_len(dev, base_idx) / 8; + if (idx >= max_port) + return 1; + } + + offset = board->first_uart_offset; + + /* + * Timedia/SUNIX uses a mixture of BARs and offsets + * Ugh, this is ugly as all hell --- TYT + */ + if (dev->vendor == PCI_VENDOR_ID_TIMEDIA) + switch(idx) { + case 0: + base_idx = 0; + break; + case 1: + base_idx = 0; + offset = 8; + break; + case 2: + base_idx = 1; + break; + case 3: + base_idx = 1; + offset = 8; + break; + case 4: /* BAR 2 */ + case 5: /* BAR 3 */ + case 6: /* BAR 4 */ + case 7: /* BAR 5 */ + base_idx = idx - 2; + } + + /* AFAVLAB uses a different mixture of BARs and offsets */ + /* Not that ugly ;) -- HW */ + if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) { + base_idx = 4; + offset = (idx - 4) * 8; + } + + /* Some Titan cards are also a little weird */ + if (dev->vendor == PCI_VENDOR_ID_TITAN && + (dev->device == PCI_DEVICE_ID_TITAN_400L || + dev->device == PCI_DEVICE_ID_TITAN_800L)) { + switch (idx) { + case 0: base_idx = 1; + break; + case 1: base_idx = 2; + break; + default: + base_idx = 4; + offset = 8 * (idx - 2); + } + } + + port = pci_resource_start(dev, base_idx) + offset; + + if ((board->flags & SPCI_FL_BASE_TABLE) == 0) + port += idx * (board->uart_offset ? board->uart_offset : 8); + + if (IS_PCI_REGION_IOPORT(dev, base_idx)) { + req->port = port; + if (HIGH_BITS_OFFSET) + req->port_high = port >> HIGH_BITS_OFFSET; + else + req->port_high = 0; + return 0; + } + req->io_type = SERIAL_IO_MEM; + req->iomem_base = ioremap(port, board->uart_offset); + if (req->iomem_base == NULL) + return -ENOMEM; + req->iomem_reg_shift = board->reg_shift; + req->port = 0; + return 0; +} + +static _INLINE_ int +get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +{ + int base_idx; + + if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) + return dev->irq; + + base_idx = SPCI_FL_GET_IRQBASE(board->flags); + if (board->flags & SPCI_FL_IRQ_TABLE) + base_idx += idx; + + return PCI_IRQ_RESOURCE(dev, base_idx); +} + +/* + * Some PCI serial cards using the PLX 9050 PCI interface chip require + * that the card interrupt be explicitly enabled or disabled. This + * seems to be mainly needed on card using the PLX which also use I/O + * mapped memory. + */ +static int __devinit +pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + u8 *p, irq_config = 0; + + if (enable) { + irq_config = 0x41; + if (dev->vendor == PCI_VENDOR_ID_PANACOM) + irq_config = 0x43; + if ((dev->vendor == PCI_VENDOR_ID_PLX) && + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { + /* + * As the megawolf cards have the int pins active + * high, and have 2 UART chips, both ints must be + * enabled on the 9050. Also, the UARTS are set in + * 16450 mode by default, so we have to enable the + * 16C950 'enhanced' mode so that we can use the + * deep FIFOs + */ + irq_config = 0x5b; + } + } + + /* + * enable/disable interrupts + */ + p = ioremap(pci_resource_start(dev, 0), 0x80); + if (p == NULL) + return -ENOMEM; + writel(irq_config, (unsigned long)p + 0x4c); + + /* + * Read the register back to ensure that it took effect. + */ + readl((unsigned long)p + 0x4c); + iounmap(p); + + return 0; +} + + +/* + * SIIG serial cards have an PCI interface chip which also controls + * the UART clocking frequency. Each UART can be clocked independently + * (except cards equiped with 4 UARTs) and initial clocking settings + * are stored in the EEPROM chip. It can cause problems because this + * version of serial driver doesn't support differently clocked UART's + * on single PCI card. To prevent this, initialization functions set + * high frequency clocking for all UART's on given card. It is safe (I + * hope) because it doesn't touch EEPROM settings to prevent conflicts + * with other OSes (like M$ DOS). + * + * SIIG support added by Andrey Panin , 10/1999 + * + * There is two family of SIIG serial cards with different PCI + * interface chip and different configuration methods: + * - 10x cards have control registers in IO and/or memory space; + * - 20x cards have control registers in standard PCI configuration space. + */ + +#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) +#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) + +static int __devinit +pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + u16 data, *p; + + if (!enable) + return 0; + + switch (dev->device & 0xfff8) { + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ + data = 0xffdf; + break; + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ + data = 0xf7ff; + break; + default: /* 1S1P, 4S */ + data = 0xfffb; + break; + } + + p = ioremap(pci_resource_start(dev, 0), 0x80); + if (p == NULL) + return -ENOMEM; + + writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); + iounmap(p); + return 0; +} + +#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) +#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) + +static int __devinit +pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + u8 data; + + if (!enable) + return 0; + + /* Change clock frequency for the first UART. */ + pci_read_config_byte(dev, 0x6f, &data); + pci_write_config_byte(dev, 0x6f, data & 0xef); + + /* If this card has 2 UART, we have to do the same with second UART. */ + if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) || + ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) { + pci_read_config_byte(dev, 0x73, &data); + pci_write_config_byte(dev, 0x73, data & 0xef); + } + return 0; +} + +/* Added for EKF Intel i960 serial boards */ +static int __devinit +pci_inteli960ni_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + unsigned long oldval; + + if (!(pci_get_subdevice(dev) & 0x1000)) + return -ENODEV; + + if (!enable) /* is there something to deinit? */ + return 0; + + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, (void*) &oldval); + if (oldval == 0x00001000L) { /* RESET value */ + printk(KERN_DEBUG "Local i960 firmware missing"); + return -ENODEV; + } + return 0; +} + +/* + * Timedia has an explosion of boards, and to avoid the PCI table from + * growing *huge*, we use this function to collapse some 70 entries + * in the PCI table into one, for sanity's and compactness's sake. + */ +static unsigned short timedia_single_port[] = { + 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 +}; + +static unsigned short timedia_dual_port[] = { + 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, + 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, + 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, + 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, + 0xD079, 0 +}; + +static unsigned short timedia_quad_port[] = { + 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, + 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, + 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, + 0xB157, 0 +}; + +static unsigned short timedia_eight_port[] = { + 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, + 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 +}; + +static struct timedia_struct { + int num; + unsigned short *ids; +} timedia_data[] = { + { 1, timedia_single_port }, + { 2, timedia_dual_port }, + { 4, timedia_quad_port }, + { 8, timedia_eight_port }, + { 0, 0 } +}; + +static int __devinit +pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + int i, j; + unsigned short *ids; + + if (!enable) + return 0; + + for (i = 0; timedia_data[i].num; i++) { + ids = timedia_data[i].ids; + for (j = 0; ids[j]; j++) { + if (pci_get_subdevice(dev) == ids[j]) { + board->num_ports = timedia_data[i].num; + return 0; + } + } + } + return 0; +} + +static int __devinit +pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/10); + return 0; +} + +/* + * This is the configuration table for all of the PCI serial boards + * which we support. It is directly indexed by the pci_board_num_t enum + * value, which is encoded in the pci_device_id PCI probe table's + * driver_data member. + */ +enum pci_board_num_t { + pbn_b0_1_115200, + pbn_default = 0, + + pbn_b0_2_115200, + pbn_b0_4_115200, + + pbn_b0_1_921600, + pbn_b0_2_921600, + pbn_b0_4_921600, + + pbn_b0_bt_1_115200, + pbn_b0_bt_2_115200, + pbn_b0_bt_8_115200, + pbn_b0_bt_1_460800, + pbn_b0_bt_2_460800, + + pbn_b1_1_115200, + pbn_b1_2_115200, + pbn_b1_4_115200, + pbn_b1_8_115200, + + pbn_b1_2_921600, + pbn_b1_4_921600, + pbn_b1_8_921600, + + pbn_b1_2_1382400, + pbn_b1_4_1382400, + pbn_b1_8_1382400, + + pbn_b2_8_115200, + pbn_b2_4_460800, + pbn_b2_8_460800, + pbn_b2_16_460800, + pbn_b2_4_921600, + pbn_b2_8_921600, + + pbn_b2_bt_1_115200, + pbn_b2_bt_2_115200, + pbn_b2_bt_4_115200, + pbn_b2_bt_2_921600, + + pbn_panacom, + pbn_panacom2, + pbn_panacom4, + pbn_plx_romulus, + pbn_oxsemi, + pbn_timedia, + pbn_intel_i960, + pbn_sgi_ioc3, + pbn_nec_nile4, + + pbn_dci_pccom4, + pbn_dci_pccom8, + + pbn_xircom_combo, + + pbn_siig10x_0, + pbn_siig10x_1, + pbn_siig10x_2, + pbn_siig10x_4, + pbn_siig20x_0, + pbn_siig20x_2, + pbn_siig20x_4, + + pbn_computone_4, + pbn_computone_6, + pbn_computone_8, +}; + +static struct pci_board pci_boards[] __devinitdata = { + /* + * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, + * Offset to get to next UART's registers, + * Register shift to use for memory-mapped I/O, + * Initialization function, first UART offset + */ + + /* Generic serial board, pbn_b0_1_115200, pbn_default */ + { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, + pbn_default */ + + { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ + { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ + + { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ + { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ + { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ + + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ + + { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ + { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ + { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ + { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ + + { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ + { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ + { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ + + { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ + { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ + { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ + + { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ + { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ + { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ + { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ + { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ + { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ + + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ + + { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ + 0x400, 7, pci_plx9050_fn }, + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ + 0x400, 7, pci_plx9050_fn }, + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ + 0x400, 7, pci_plx9050_fn }, + { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ + 0x20, 2, pci_plx9050_fn, 0x03 }, + /* This board uses the size of PCI Base region 0 to + * signal now many ports are available */ + { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ + { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ + 0, 0, pci_timedia_fn }, + /* EKF addition for i960 Boards form EKF with serial port */ + { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ + 8<<2, 2, pci_inteli960ni_fn, 0x10000}, + { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ + 1, 458333, 0, 0, 0, 0x20178 }, + + /* + * NEC Vrc-5074 (Nile 4) builtin UART. + */ + { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ + 64, 3, NULL, 0x300 }, + + { SPCI_FL_BASE3, 4, 115200, 8 }, /* pbn_dci_pccom4 */ + { SPCI_FL_BASE3, 8, 115200, 8 }, /* pbn_dci_pccom8 */ + + { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ + 0, 0, pci_xircom_fn }, + + { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ + 0, 0, pci_siig10x_fn }, + { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ + 0, 0, pci_siig10x_fn }, + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ + 0, 0, pci_siig10x_fn }, + { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ + 0, 0, pci_siig10x_fn }, + { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ + 0, 0, pci_siig20x_fn }, + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ + 0, 0, pci_siig20x_fn }, + { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ + 0, 0, pci_siig20x_fn }, + + { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ + 0x40, 2, NULL, 0x200 }, + { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ + 0x40, 2, NULL, 0x200 }, + { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ + 0x40, 2, NULL, 0x200 }, +}; + +/* + * Given a complete unknown PCI device, try to use some heuristics to + * guess what the configuration might be, based on the pitiful PCI + * serial specs. Returns 0 on success, 1 on failure. + */ +static int __devinit +serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) +{ + int num_iomem = 0, num_port = 0, first_port = -1; + int i; + + /* + * If it is not a communications device or the programming + * interface is greater than 6, give up. + * + * (Should we try to make guesses for multiport serial devices + * later?) + */ + if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) && + ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) || + (dev->class & 0xff) > 6) + return 1; + + for (i = 0; i < 6; i++) { + if (IS_PCI_REGION_IOPORT(dev, i)) { + num_port++; + if (first_port == -1) + first_port = i; + } + if (IS_PCI_REGION_IOMEM(dev, i)) + num_iomem++; + } + + /* + * If there is 1 or 0 iomem regions, and exactly one port, use + * it. + */ + if (num_iomem <= 1 && num_port == 1) { + board->flags = first_port; + return 0; + } + return 1; +} + +/* + * return an error code to refuse. + * + * serial_struct is 60 bytes. + */ +static int __devinit pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +{ + struct serial_private *priv; + struct pci_board *board, tmp; + struct serial_struct serial_req; + int base_baud, rc, k; + + if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { + printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", + ent->driver_data); + return -EINVAL; + } + + board = &pci_boards[ent->driver_data]; + + rc = pci_enable_device(dev); + if (rc) + return rc; + + if (ent->driver_data == pbn_default && + serial_pci_guess_board(dev, board)) + return -ENODEV; + else if (serial_pci_guess_board(dev, &tmp) == 0) { + printk(KERN_INFO "Redundant entry in serial pci_table. " + "Please send the output of\n" + "lspci -vv, this message (%d,%d,%d,%d)\n" + "and the manufacturer and name of " + "serial board or modem board\n" + "to serial-pci-info@lists.sourceforge.net.\n", + dev->vendor, dev->device, + pci_get_subvendor(dev), pci_get_subdevice(dev)); + } + + priv = kmalloc(sizeof(struct serial_private) + + sizeof(unsigned int) * board->num_ports, + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* + * Run the initialization function, if any + */ + if (board->init_fn) { + rc = board->init_fn(dev, board, 1); + if (rc != 0) { + kfree(priv); + return rc; + } + } + + base_baud = board->base_baud; + if (!base_baud) + base_baud = BASE_BAUD; + memset(&serial_req, 0, sizeof(serial_req)); + for (k = 0; k < board->num_ports; k++) { + serial_req.irq = get_pci_irq(dev, board, k); + if (get_pci_port(dev, board, &serial_req, k)) + break; +#ifdef SERIAL_DEBUG_PCI + printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", + serial_req.port, serial_req.irq, serial_req.io_type); +#endif + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; + serial_req.baud_base = base_baud; + + priv->line[k] = register_serial(&serial_req); + if (priv->line[k] < 0) + break; + } + + priv->board = board; + priv->nr = k; + + pci_set_drvdata(dev, priv); + + return 0; +} + +static void __devexit pci_remove_one(struct pci_dev *dev) +{ + struct serial_private *priv = pci_get_drvdata(dev); + int i; + + pci_set_drvdata(dev, NULL); + + if (priv) { + for (i = 0; i < priv->nr; i++) + unregister_serial(priv->line[i]); + + priv->board->init_fn(dev, priv->board, 0); + + pci_disable_device(dev); + + kfree(priv); + } +} + +static struct pci_device_id serial_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, + pbn_b1_8_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, + pbn_b1_4_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, + pbn_b1_2_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, + pbn_b1_8_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, + pbn_b1_4_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, + pbn_b1_2_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0, + pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0, + pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0, + pbn_b1_2_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, + pbn_b1_4_921600 }, + + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_1_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_115200 }, + + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_921600 }, + /* VScom SPCOM800, from sl@s.pl */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_921600 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_4_921600 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_KEYSPAN, + PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, + pbn_panacom }, + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_panacom4 }, + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_panacom2 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, + pbn_b2_4_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, + pbn_b2_8_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, + pbn_b2_16_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, + pbn_b2_16_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIRAS, + PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, + pbn_b2_4_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIRAS, + PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, + pbn_b2_8_460800 }, + /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ + /* (Exoray@isys.ca) */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, + 0x10b5, 0x106a, 0, 0, + pbn_plx_romulus }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + 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 }, + + /* Digitan DS560-558, from jimd@esoft.com */ + { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_115200 }, + + /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ + { PCI_VENDOR_ID_USR, 0x1008, + PCI_ANY_ID, PCI_ANY_ID, }, + + /* Titan Electronic cards */ + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_2_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE1, 1, 921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, + /* The 400L and 800L have a custom hack in get_pci_port */ + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE_TABLE, 4, 921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, + PCI_ANY_ID, PCI_ANY_ID, + SPCI_FL_BASE_TABLE, 8, 921600 }, + + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_1 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_1 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_1 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_4 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_4 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig10x_4 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_0 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_2 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_4 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_4 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_siig20x_4 }, + + /* Computone devices submitted by Doug McNash dmcnash@computone.com */ + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, + 0, 0, pbn_computone_4 }, + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8, + 0, 0, pbn_computone_8 }, + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6, + 0, 0, pbn_computone_6 }, + + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, + { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, + + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + /* 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_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_460800 }, + + /* RAStel 2 port modem, gerg@moreton.com.au */ + { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + + /* EKF addition for i960 Boards form EKF with serial port */ + { PCI_VENDOR_ID_INTEL, 0x1960, + 0xE4BF, PCI_ANY_ID, 0, 0, + pbn_intel_i960 }, + + /* Xircom Cardbus/Ethernet combos */ + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_xircom_combo }, + + /* + * Untested PCI modems, sent in from various folks... + */ + + /* Elsa Model 56K PCI Modem, from Andreas Rath */ + { PCI_VENDOR_ID_ROCKWELL, 0x1004, + 0x1048, 0x1500, 0, 0, + pbn_b1_1_115200 }, + + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + 0xFF00, 0, 0, 0, + pbn_sgi_ioc3 }, + + /* + * NEC Vrc-5074 (Nile 4) builtin UART. + */ + { PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_nec_nile4 }, + + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_dci_pccom4 }, + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_dci_pccom8 }, + + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, + 0xffff00, }, + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MODEM << 8, + 0xffff00, }, + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, + 0xffff00, }, + { 0, } +}; + +#ifndef __devexit_p +#if defined(MODULE) || defined(CONFIG_HOTPLUG) +#define __devexit_p(x) x +#else +#define __devexit_p(x) NULL +#endif +#endif + +static struct pci_driver serial_pci_driver = { + name: "serial", + probe: pci_init_one, + remove: __devexit_p(pci_remove_one), + id_table: serial_pci_tbl, +}; + +static int __init serial8250_pci_init(void) +{ + return pci_module_init(&serial_pci_driver); +} + +static void __exit serial8250_pci_exit(void) +{ + pci_unregister_driver(&serial_pci_driver); +} + +module_init(serial8250_pci_init); +module_exit(serial8250_pci_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module"); +MODULE_DEVICE_TABLE(pci, serial_pci_tbl); diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/8250_pnp.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,548 @@ +/* + * linux/drivers/char/8250_pnp.c + * + * Probe module for 8250/16550-type ISAPNP serial ports. + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2001 Russell King, 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. + * + * $Id: 8250_pnp.c,v 1.10 2002/07/21 21:32:30 rmk Exp $ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "8250.h" + +struct pnpbios_device_id +{ + char id[8]; + unsigned long driver_data; +}; + +static const struct pnpbios_device_id pnp_dev_table[] = { + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { "AAC000F", 0 }, + /* Anchor Datacomm BV */ + /* SXPro 144 External Data Fax Modem Plug & Play */ + { "ADC0001", 0 }, + /* SXPro 288 External Data Fax Modem Plug & Play */ + { "ADC0002", 0 }, + /* Rockwell 56K ACF II Fax+Data+Voice Modem */ + { "AKY1021", SPCI_FL_NO_SHIRQ }, + /* AZT3005 PnP SOUND DEVICE */ + { "AZT4001", 0 }, + /* Best Data Products Inc. Smart One 336F PnP Modem */ + { "BDP3336", 0 }, + /* Boca Research */ + /* Boca Complete Ofc Communicator 14.4 Data-FAX */ + { "BRI0A49", 0 }, + /* Boca Research 33,600 ACF Modem */ + { "BRI1400", 0 }, + /* Boca 33.6 Kbps Internal FD34FSVD */ + { "BRI3400", 0 }, + /* Boca 33.6 Kbps Internal FD34FSVD */ + { "BRI0A49", 0 }, + /* Best Data Products Inc. Smart One 336F PnP Modem */ + { "BDP3336", 0 }, + /* Computer Peripherals Inc */ + /* EuroViVa CommCenter-33.6 SP PnP */ + { "CPI4050", 0 }, + /* Creative Labs */ + /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */ + { "CTL3001", 0 }, + /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ + { "CTL3011", 0 }, + /* Creative */ + /* Creative Modem Blaster Flash56 DI5601-1 */ + { "DMB1032", 0 }, + /* Creative Modem Blaster V.90 DI5660 */ + { "DMB2001", 0 }, + /* FUJITSU */ + /* Fujitsu 33600 PnP-I2 R Plug & Play */ + { "FUJ0202", 0 }, + /* Fujitsu FMV-FX431 Plug & Play */ + { "FUJ0205", 0 }, + /* Fujitsu 33600 PnP-I4 R Plug & Play */ + { "FUJ0206", 0 }, + /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */ + { "FUJ0209", 0 }, + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { "GVC000F", 0 }, + /* Hayes */ + /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */ + { "HAY0001", 0 }, + /* Hayes Optima 336 V.34 + FAX + Voice PnP */ + { "HAY000C", 0 }, + /* Hayes Optima 336B V.34 + FAX + Voice PnP */ + { "HAY000D", 0 }, + /* Hayes Accura 56K Ext Fax Modem PnP */ + { "HAY5670", 0 }, + /* Hayes Accura 56K Ext Fax Modem PnP */ + { "HAY5674", 0 }, + /* Hayes Accura 56K Fax Modem PnP */ + { "HAY5675", 0 }, + /* Hayes 288, V.34 + FAX */ + { "HAYF000", 0 }, + /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */ + { "HAYF001", 0 }, + /* IBM */ + /* IBM Thinkpad 701 Internal Modem Voice */ + { "IBM0033", 0 }, + /* Intertex */ + /* Intertex 28k8 33k6 Voice EXT PnP */ + { "IXDC801", 0 }, + /* Intertex 33k6 56k Voice EXT PnP */ + { "IXDC901", 0 }, + /* Intertex 28k8 33k6 Voice SP EXT PnP */ + { "IXDD801", 0 }, + /* Intertex 33k6 56k Voice SP EXT PnP */ + { "IXDD901", 0 }, + /* Intertex 28k8 33k6 Voice SP INT PnP */ + { "IXDF401", 0 }, + /* Intertex 28k8 33k6 Voice SP EXT PnP */ + { "IXDF801", 0 }, + /* Intertex 33k6 56k Voice SP EXT PnP */ + { "IXDF901", 0 }, + /* Kortex International */ + /* KORTEX 28800 Externe PnP */ + { "KOR4522", 0 }, + /* KXPro 33.6 Vocal ASVD PnP */ + { "KORF661", 0 }, + /* Lasat */ + /* LASAT Internet 33600 PnP */ + { "LAS4040", 0 }, + /* Lasat Safire 560 PnP */ + { "LAS4540", 0 }, + /* Lasat Safire 336 PnP */ + { "LAS5440", 0 }, + /* Microcom, Inc. */ + /* Microcom TravelPorte FAST V.34 Plug & Play */ + { "MNP0281", 0 }, + /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */ + { "MNP0336", 0 }, + /* Microcom DeskPorte FAST EP 28.8 Plug & Play */ + { "MNP0339", 0 }, + /* Microcom DeskPorte 28.8P Plug & Play */ + { "MNP0342", 0 }, + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ + { "MNP0500", 0 }, + /* Microcom DeskPorte FAST ES 28.8 Plug & Play */ + { "MNP0501", 0 }, + /* Microcom DeskPorte 28.8S Internal Plug & Play */ + { "MNP0502", 0 }, + /* Motorola */ + /* Motorola BitSURFR Plug & Play */ + { "MOT1105", 0 }, + /* Motorola TA210 Plug & Play */ + { "MOT1111", 0 }, + /* Motorola HMTA 200 (ISDN) Plug & Play */ + { "MOT1114", 0 }, + /* Motorola BitSURFR Plug & Play */ + { "MOT1115", 0 }, + /* Motorola Lifestyle 28.8 Internal */ + { "MOT1190", 0 }, + /* Motorola V.3400 Plug & Play */ + { "MOT1501", 0 }, + /* Motorola Lifestyle 28.8 V.34 Plug & Play */ + { "MOT1502", 0 }, + /* Motorola Power 28.8 V.34 Plug & Play */ + { "MOT1505", 0 }, + /* Motorola ModemSURFR External 28.8 Plug & Play */ + { "MOT1509", 0 }, + /* Motorola Premier 33.6 Desktop Plug & Play */ + { "MOT150A", 0 }, + /* Motorola VoiceSURFR 56K External PnP */ + { "MOT150F", 0 }, + /* Motorola ModemSURFR 56K External PnP */ + { "MOT1510", 0 }, + /* Motorola ModemSURFR 56K Internal PnP */ + { "MOT1550", 0 }, + /* Motorola ModemSURFR Internal 28.8 Plug & Play */ + { "MOT1560", 0 }, + /* Motorola Premier 33.6 Internal Plug & Play */ + { "MOT1580", 0 }, + /* Motorola OnlineSURFR 28.8 Internal Plug & Play */ + { "MOT15B0", 0 }, + /* Motorola VoiceSURFR 56K Internal PnP */ + { "MOT15F0", 0 }, + /* Com 1 */ + /* Deskline K56 Phone System PnP */ + { "MVX00A1", 0 }, + /* PC Rider K56 Phone System PnP */ + { "MVX00F2", 0 }, + /* Pace 56 Voice Internal Plug & Play Modem */ + { "PMC2430", 0 }, + /* Generic */ + /* Generic standard PC COM port */ + { "PNP0500", 0 }, + /* Generic 16550A-compatible COM port */ + { "PNP0501", 0 }, + /* Compaq 14400 Modem */ + { "PNPC000", 0 }, + /* Compaq 2400/9600 Modem */ + { "PNPC001", 0 }, + /* Dial-Up Networking Serial Cable between 2 PCs */ + { "PNPC031", 0 }, + /* Dial-Up Networking Parallel Cable between 2 PCs */ + { "PNPC032", 0 }, + /* Standard 9600 bps Modem */ + { "PNPC100", 0 }, + /* Standard 14400 bps Modem */ + { "PNPC101", 0 }, + /* Standard 28800 bps Modem*/ + { "PNPC102", 0 }, + /* Standard Modem*/ + { "PNPC103", 0 }, + /* Standard 9600 bps Modem*/ + { "PNPC104", 0 }, + /* Standard 14400 bps Modem*/ + { "PNPC105", 0 }, + /* Standard 28800 bps Modem*/ + { "PNPC106", 0 }, + /* Standard Modem */ + { "PNPC107", 0 }, + /* Standard 9600 bps Modem */ + { "PNPC108", 0 }, + /* Standard 14400 bps Modem */ + { "PNPC109", 0 }, + /* Standard 28800 bps Modem */ + { "PNPC10A", 0 }, + /* Standard Modem */ + { "PNPC10B", 0 }, + /* Standard 9600 bps Modem */ + { "PNPC10C", 0 }, + /* Standard 14400 bps Modem */ + { "PNPC10D", 0 }, + /* Standard 28800 bps Modem */ + { "PNPC10E", 0 }, + /* Standard Modem */ + { "PNPC10F", 0 }, + /* Standard PCMCIA Card Modem */ + { "PNP2000", 0 }, + /* Rockwell */ + /* Modular Technology */ + /* Rockwell 33.6 DPF Internal PnP */ + /* Modular Technology 33.6 Internal PnP */ + { "ROK0030", 0 }, + /* Kortex International */ + /* KORTEX 14400 Externe PnP */ + { "ROK0100", 0 }, + /* Viking Components, Inc */ + /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */ + { "ROK4920", 0 }, + /* Rockwell */ + /* British Telecom */ + /* Modular Technology */ + /* Rockwell 33.6 DPF External PnP */ + /* BT Prologue 33.6 External PnP */ + /* Modular Technology 33.6 External PnP */ + { "RSS00A0", 0 }, + /* Viking 56K FAX INT */ + { "RSS0262", 0 }, + /* SupraExpress 28.8 Data/Fax PnP modem */ + { "SUP1310", 0 }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { "SUP1421", 0 }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { "SUP1590", 0 }, + /* SupraExpress 33.6 Data/Fax PnP modem */ + { "SUP1760", 0 }, + /* Phoebe Micro */ + /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */ + { "TEX0011", 0 }, + /* Archtek America Corp. */ + /* Archtek SmartLink Modem 3334BT Plug & Play */ + { "UAC000F", 0 }, + /* 3Com Corp. */ + /* Gateway Telepath IIvi 33.6 */ + { "USR0000", 0 }, + /* Sportster Vi 14.4 PnP FAX Voicemail */ + { "USR0004", 0 }, + /* U.S. Robotics 33.6K Voice INT PnP */ + { "USR0006", 0 }, + /* U.S. Robotics 33.6K Voice EXT PnP */ + { "USR0007", 0 }, + /* U.S. Robotics 33.6K Voice INT PnP */ + { "USR2002", 0 }, + /* U.S. Robotics 56K Voice INT PnP */ + { "USR2070", 0 }, + /* U.S. Robotics 56K Voice EXT PnP */ + { "USR2080", 0 }, + /* U.S. Robotics 56K FAX INT */ + { "USR3031", 0 }, + /* U.S. Robotics 56K Voice INT PnP */ + { "USR3070", 0 }, + /* U.S. Robotics 56K Voice EXT PnP */ + { "USR3080", 0 }, + /* U.S. Robotics 56K Voice INT PnP */ + { "USR3090", 0 }, + /* U.S. Robotics 56K Message */ + { "USR9100", 0 }, + /* U.S. Robotics 56K FAX EXT PnP*/ + { "USR9160", 0 }, + /* U.S. Robotics 56K FAX INT PnP*/ + { "USR9170", 0 }, + /* U.S. Robotics 56K Voice EXT PnP*/ + { "USR9180", 0 }, + /* U.S. Robotics 56K Voice INT PnP*/ + { "USR9190", 0 }, + { "", 0 } +}; + +static void inline avoid_irq_share(struct pci_dev *dev) +{ + unsigned int map = 0x1FF8; + struct isapnp_irq *irq; + struct isapnp_resources *res = dev->sysdata; + + serial8250_get_irq_map(&map); + + for ( ; res; res = res->alt) + for (irq = res->irq; irq; irq = irq->next) + irq->map = map; +} + +static char *modem_names[] __devinitdata = { + "MODEM", "Modem", "modem", "FAX", "Fax", "fax", + "56K", "56k", "K56", "33.6", "28.8", "14.4", + "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", + "33600", "28800", "14400", "V.90", "V.34", "V.32", 0 +}; + +static int __devinit check_name(char *name) +{ + char **tmp; + + for (tmp = modem_names; *tmp; tmp++) + if (strstr(name, *tmp)) + return 1; + + return 0; +} + +static int inline check_compatible_id(struct pci_dev *dev) +{ + int i; + for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++) + if ((dev->vendor_compatible[i] == + ISAPNP_VENDOR('P', 'N', 'P')) && + (swab16(dev->device_compatible[i]) >= 0xc000) && + (swab16(dev->device_compatible[i]) <= 0xdfff)) + return 0; + return 1; +} + +/* + * Given a complete unknown ISA PnP device, try to use some heuristics to + * detect modems. Currently use such heuristic set: + * - dev->name or dev->bus->name must contain "modem" substring; + * - device must have only one IO region (8 byte long) with base adress + * 0x2e8, 0x3e8, 0x2f8 or 0x3f8. + * + * Such detection looks very ugly, but can detect at least some of numerous + * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] + * table. + */ +static int serial_pnp_guess_board(struct pci_dev *dev, int *flags) +{ + struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; + struct isapnp_resources *resa; + + if (!(check_name(dev->name) || check_name(dev->bus->name)) && + !(check_compatible_id(dev))) + return -ENODEV; + + if (!res || res->next) + return -ENODEV; + + for (resa = res->alt; resa; resa = resa->alt) { + struct isapnp_port *port; + for (port = res->port; port; port = port->next) + if ((port->size == 8) && + ((port->min == 0x2f8) || + (port->min == 0x3f8) || + (port->min == 0x2e8) || + (port->min == 0x3e8))) + return 0; + } + + return -ENODEV; +} + +static int +pnp_init_one(struct pci_dev *dev, const struct pnpbios_device_id *ent, + char *slot_name) +{ + struct serial_struct serial_req; + int ret, line, flags = ent ? ent->driver_data : 0; + + if (!ent) { + ret = serial_pnp_guess_board(dev, &flags); + if (ret) + return ret; + } + + if (dev->prepare(dev) < 0) { + printk("serial: PNP device '%s' prepare failed\n", + slot_name); + return -ENODEV; + } + + if (dev->active) + return -ENODEV; + + if (flags & SPCI_FL_NO_SHIRQ) + avoid_irq_share(dev); + + if (dev->activate(dev) < 0) { + printk("serial: PNP device '%s' activate failed\n", + slot_name); + return -ENODEV; + } + + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.irq = dev->irq_resource[0].start; + serial_req.port = pci_resource_start(dev, 0); + if (HIGH_BITS_OFFSET) + serial_req.port = pci_resource_start(dev, 0) >> HIGH_BITS_OFFSET; + +#ifdef SERIAL_DEBUG_PNP + printk("Setup PNP port: port %x, irq %d, type %d\n", + serial_req.port, serial_req.irq, serial_req.io_type); +#endif + + serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; + serial_req.baud_base = 115200; + line = register_serial(&serial_req); + + if (line >= 0) { + pci_set_drvdata(dev, (void *)(line + 1)); + + /* + * Public health warning: remove this once the 2.5 + * pnpbios_module_init() stuff is incorporated. + */ + dev->driver = (void *)pnp_dev_table; + } else + dev->deactivate(dev); + + return line >= 0 ? 0 : -ENODEV; +} + +static void pnp_remove_one(struct pci_dev *dev) +{ + int line = (int)pci_get_drvdata(dev); + + if (line) { + pci_set_drvdata(dev, NULL); + + unregister_serial(line - 1); + + dev->deactivate(dev); + } +} + +static char hex[] = "0123456789ABCDEF"; + +/* + * This function should vanish when 2.5 comes around and + * we have pnpbios_module_init() + */ +static int pnp_init(void) +{ + const struct pnpbios_device_id *id; + struct pci_dev *dev = NULL; + int nr = 0, rc = -ENODEV; + +#ifdef SERIAL_DEBUG_PNP + printk("Entered probe_serial_pnp()\n"); +#endif + + isapnp_for_each_dev(dev) { + char slot_name[8]; + u32 pnpid; + + if (dev->active) + continue; + + pnpid = dev->vendor << 16 | dev->device; + pnpid = cpu_to_le32(pnpid); + +#define HEX(id,a) hex[((id)>>a) & 15] +#define CHAR(id,a) (0x40 + (((id)>>a) & 31)) + slot_name[0] = CHAR(pnpid, 26); + slot_name[1] = CHAR(pnpid, 21); + slot_name[2] = CHAR(pnpid, 16); + slot_name[3] = HEX(pnpid, 12); + slot_name[4] = HEX(pnpid, 8); + slot_name[5] = HEX(pnpid, 4); + slot_name[6] = HEX(pnpid, 0); + slot_name[7] = '\0'; + + for (id = pnp_dev_table; id->id[0]; id++) + if (memcmp(id->id, slot_name, 7) == 0) + break; + + if (id->id[0]) + rc = pnp_init_one(dev, id, slot_name); + else + rc = pnp_init_one(dev, NULL, slot_name); + + if (rc == 0) + nr++; + } + +#ifdef SERIAL_DEBUG_PNP + printk("Leaving probe_serial_pnp() (probe finished)\n"); +#endif + + return nr == 0 ? rc : 0; +} + +static int __init serial8250_pnp_init(void) +{ + if (!isapnp_present()) { +#ifdef SERIAL_DEBUG_PNP + printk("Leaving probe_serial_pnp() (no isapnp)\n"); +#endif + return -ENODEV; + } + return pnp_init(); +} + +static void __exit serial8250_pnp_exit(void) +{ + struct pci_dev *dev = NULL; + + isapnp_for_each_dev(dev) { + if (dev->driver != (void *)pnp_dev_table) + continue; + pnp_remove_one(dev); + } +} + +module_init(serial8250_pnp_init); +module_exit(serial8250_pnp_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module"); +MODULE_DEVICE_TABLE(pnpbios, pnp_dev_table); diff -Nru a/drivers/serial/Config.help b/drivers/serial/Config.help --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/Config.help Wed Jul 24 14:03:39 2002 @@ -0,0 +1,225 @@ +# $Id: Config.help,v 1.5 2002/07/06 17:16:24 rmk Exp $ + +CONFIG_SERIAL_8250 + 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.) + + If you want to compile this driver as a module, say M here and read + . The module will be called + serial.o. + [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_8250_CONSOLE + 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). This could be useful if some terminal or printer is connected + to that serial port. + + 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=ttyS1". (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 you don't have a VGA card installed and you say Y here, the + kernel will automatically use the first serial line, /dev/ttyS0, as + system console. + + If unsure, say N. + +CONFIG_SERIAL_8250_CS + Say Y here to enable support for 16-bit PCMCIA serial devices, + including serial port cards, modems, and the modem functions of + multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called serial_cs.o. If you want to compile it as + a module, say M here and read . + If unsure, say N. + +CONFIG_SERIAL_8250_EXTENDED + 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_8250_MANY_PORTS + 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_8250_SHARE_IRQ + 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_8250_DETECT_IRQ + Say Y here if you want the kernel to try to guess which IRQ + to use for your serial port. + + This is considered unsafe; it is far better to configure the IRQ in + a boot script using the setserial command. + + If unsure, say N. + +CONFIG_SERIAL_8250_MULTIPORT + 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_SERIAL_8250_RSA + ::: To be written ::: + +CONFIG_ATOMWIDE_SERIAL + If you have an Atomwide Serial card for an Acorn system, say Y to + this option. The driver can handle 1, 2, or 3 port cards. + If unsure, say N. + +CONFIG_DUALSP_SERIAL + If you have the Serial Port's dual serial card for an Acorn system, + say Y to this option. If unsure, say N. + +CONFIG_SERIAL_ANAKIN + ::: To be written ::: +CONFIG_SERIAL_ANAKIN_CONSOLE + ::: To be written ::: + + 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=ttyAN0". (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_ANAKIN_DEFAULT_BAUDRATE + ::: To be written ::: + +CONFIG_SERIAL_AMBA + This selects the ARM(R) AMBA(R) PrimeCell UART. If you have an + Integrator platform, say Y or M here. + + If unsure, say N. + +CONFIG_SERIAL_AMBA_CONSOLE + Say Y here if you wish to use an AMBA PrimeCell UART 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). + + Even if you say Y here, the currently visible framebuffer 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=ttyAM0". (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_CLPS711X + ::: To be written ::: + +CONFIG_SERIAL_CLPS711X_CONSOLE + ::: To be written ::: + + 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=ttyCL1". (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_CLPS711X_OLD_NAME + ::: To be written ::: + +CONFIG_SERIAL_21285 + If you have a machine based on a 21285 (Footbridge) StrongARM(R)/ + PCI bridge you can enable its onboard serial port by enabling this + option. + +CONFIG_SERIAL_21285_OLD + Use the old /dev/ttyS name, major 4 minor 64. This is obsolete + and will be removed during later 2.5 development. + +CONFIG_SERIAL_21285_CONSOLE + If you have enabled the serial port on the 21285 footbridge 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=ttyFB". (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_UART00 + Say Y here if you want to use the hard logic uart on Excalibur. This + driver also supports soft logic implentations of this uart core. + +CONFIG_SERIAL_UART00_CONSOLE + Say Y here if you want to support a serial console on an Excalibur + hard logic uart or uart00 IP core. + + 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=ttyS1". (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 + If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you + can enable its onboard serial port by enabling this option. + Please read for further + info. + +CONFIG_SERIAL_SA1100_CONSOLE + If you have enabled the serial port on the SA1100/SA1110 StrongARM + 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_L7200 +# If you have a LinkUp Systems L7200 board you can enable its two +# onboard serial ports by enabling this option. The device numbers +# are major ID 4 with minor 64 and 65 respectively. +# +#CONFIG_SERIAL_L7200_CONSOLE +# If you have enabled the serial ports on the L7200 development board +# you can make the first serial port the console by answering Y to +# this option. + diff -Nru a/drivers/serial/Config.in b/drivers/serial/Config.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/Config.in Wed Jul 24 14:03:39 2002 @@ -0,0 +1,77 @@ +# +# Serial device configuration +# +# $Id: Config.in,v 1.15 2002/07/06 17:16:24 rmk Exp $ +# +mainmenu_option next_comment +comment 'Serial drivers' + +# +# The new 8250/16550 serial drivers +dep_tristate '8250/16550 and compatible serial support (EXPERIMENTAL)' CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL +dep_bool ' Console on 8250/16550 and compatible serial port (EXPERIMENTAL)' CONFIG_SERIAL_8250_CONSOLE $CONFIG_SERIAL_8250 $CONFIG_EXPERIMENTAL +dep_tristate ' 8250/16550 PCMCIA device support' CONFIG_SERIAL_8250_CS $CONFIG_PCMCIA $CONFIG_SERIAL_8250 + +dep_mbool 'Extended 8250/16550 serial driver options' CONFIG_SERIAL_8250_EXTENDED $CONFIG_SERIAL_8250 +dep_bool ' Support more than 4 serial ports' CONFIG_SERIAL_8250_MANY_PORTS $CONFIG_SERIAL_8250_EXTENDED +dep_bool ' Support for sharing serial interrupts' CONFIG_SERIAL_8250_SHARE_IRQ $CONFIG_SERIAL_8250_EXTENDED +dep_bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_8250_DETECT_IRQ $CONFIG_SERIAL_8250_EXTENDED +dep_bool ' Support special multiport boards' CONFIG_SERIAL_8250_MULTIPORT $CONFIG_SERIAL_8250_EXTENDED +dep_bool ' Support RSA serial ports' CONFIG_SERIAL_8250_RSA $CONFIG_SERIAL_8250_EXTENDED + +comment 'Non-8250 serial port support' + +if [ "$CONFIG_ARM" = "y" ]; then + dep_tristate 'Acorn Atomwide 16550 serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_ARCH_ACORN $CONFIG_SERIAL_8250 + dep_tristate 'Acorn Dual 16550 serial port support' CONFIG_DUALSP_SERIAL $CONFIG_ARCH_ACORN $CONFIG_SERIAL_8250 + dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN + dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN + if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then + int ' Default Anakin serial baudrate' CONFIG_ANAKIN_DEFAULT_BAUDRATE 9600 + fi + + dep_tristate 'ARM AMBA serial port support' CONFIG_SERIAL_AMBA $CONFIG_ARCH_INTEGRATOR + dep_bool ' Support for console on AMBA serial port' CONFIG_SERIAL_AMBA_CONSOLE $CONFIG_SERIAL_AMBA + if [ "$CONFIG_SERIAL_AMBA" = "y" ]; then + define_bool CONFIG_SERIAL_INTEGRATOR y + fi + + dep_tristate 'CLPS711X serial port support' CONFIG_SERIAL_CLPS711X $CONFIG_ARCH_CLPS711X + dep_bool ' Support for console on CLPS711X serial port' CONFIG_SERIAL_CLPS711X_CONSOLE $CONFIG_SERIAL_CLPS711X + dep_bool ' Use the old 2.4 names for CLPS711X serial port' CONFIG_SERIAL_CLPS711X_OLD_NAME $CONFIG_SERIAL_CLPS711X + + dep_tristate 'DC21285 serial port support' CONFIG_SERIAL_21285 $CONFIG_FOOTBRIDGE + dep_bool ' Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD $CONFIG_SERIAL_21285 $CONFIG_OBSOLETE + dep_bool ' Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE $CONFIG_SERIAL_21285 + + dep_bool 'Excalibur serial port (uart00) support' CONFIG_SERIAL_UART00 $CONFIG_ARCH_CAMELOT + dep_bool ' Support for console on Excalibur serial port' CONFIG_SERIAL_UART00_CONSOLE $CONFIG_SERIAL_UART00 + + dep_bool 'SA1100 serial port support' CONFIG_SERIAL_SA1100 $CONFIG_ARCH_SA1100 + dep_bool ' Console on SA1100 serial port' CONFIG_SERIAL_SA1100_CONSOLE $CONFIG_SERIAL_SA1100 +fi + +if [ "$CONFIG_SERIAL_AMBA" = "y" -o "$CONFIG_SERIAL_CLPS711X" = "y" -o \ + "$CONFIG_SERIAL_21285" = "y" -o "$CONFIG_SERIAL_SA1100" = "y" -o \ + "$CONFIG_SERIAL_ANAKIN" = "y" -o "$CONFIG_SERIAL_UART00" = "y" -o \ + "$CONFIG_SERIAL_8250" = "y" -o "$CONFIG_SERIAL_ROCKETPORT" = "y" ]; then + define_bool CONFIG_SERIAL_CORE y +else + if [ "$CONFIG_SERIAL_AMBA" = "m" -o "$CONFIG_SERIAL_CLPS711X" = "m" -o \ + "$CONFIG_SERIAL_21285" = "m" -o "$CONFIG_SERIAL_SA1100" = "m" -o \ + "$CONFIG_SERIAL_ANAKIN" = "m" -o "$CONFIG_SERIAL_UART00" = "m" -o \ + "$CONFIG_SERIAL_8250" = "m" -o "$CONFIG_SERIAL_ROCKETPORT" = "m" ]; then + define_bool CONFIG_SERIAL_CORE m + fi +fi +if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_CLPS711X_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_21285_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_SA1100_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_ANAKIN_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_UART00_CONSOLE" = "y" -o \ + "$CONFIG_SERIAL_8250_CONSOLE" = "y" ]; then + define_bool CONFIG_SERIAL_CORE_CONSOLE y +fi + +endmenu diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/Makefile Wed Jul 24 14:03:39 2002 @@ -0,0 +1,22 @@ +# +# Makefile for the kernel serial device drivers. +# +# $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $ +# + +export-objs := core.o 8250.o + +serial-8250-y := +serial-8250-$(CONFIG_PCI) += 8250_pci.o +serial-8250-$(CONFIG_ISAPNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_CORE) += core.o +obj-$(CONFIG_SERIAL_21285) += 21285.o +obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) +obj-$(CONFIG_SERIAL_8250_CS) += 8250_cs.o +obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o +obj-$(CONFIG_SERIAL_AMBA) += amba.o +obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o +obj-$(CONFIG_SERIAL_SA1100) += sa1100.o +obj-$(CONFIG_SERIAL_UART00) += uart00.o + +include $(TOPDIR)/Rules.make diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/amba.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,774 @@ +/* + * linux/drivers/char/amba.c + * + * Driver for AMBA serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright 1999 ARM Limited + * Copyright (C) 2000 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 + * 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 + * + * $Id: amba.c,v 1.37 2002/07/22 15:27:32 rmk Exp $ + * + * This is a generic driver for ARM AMBA-type serial ports. They + * have a lot of 16550-like features, but are not register compatable. + * Note that although they do have CTS, DCD and DSR inputs, they do + * not have an RI input, nor do they have DTR or RTS outputs. If + * required, these have to be supplied via some other means (eg, GPIO) + * and hooked into this driver. + */ +#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_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#include + +#define UART_NR 2 + +#define SERIAL_AMBA_MAJOR 204 +#define SERIAL_AMBA_MINOR 16 +#define SERIAL_AMBA_NR UART_NR + +#define AMBA_ISR_PASS_LIMIT 256 + +/* + * Access macros for the AMBA UARTs + */ +#define UART_GET_INT_STATUS(p) readb((p)->membase + AMBA_UARTIIR) +#define UART_PUT_ICR(p, c) writel((c), (p)->membase + AMBA_UARTICR) +#define UART_GET_FR(p) readb((p)->membase + AMBA_UARTFR) +#define UART_GET_CHAR(p) readb((p)->membase + AMBA_UARTDR) +#define UART_PUT_CHAR(p, c) writel((c), (p)->membase + AMBA_UARTDR) +#define UART_GET_RSR(p) readb((p)->membase + AMBA_UARTRSR) +#define UART_GET_CR(p) readb((p)->membase + AMBA_UARTCR) +#define UART_PUT_CR(p,c) writel((c), (p)->membase + AMBA_UARTCR) +#define UART_GET_LCRL(p) readb((p)->membase + AMBA_UARTLCR_L) +#define UART_PUT_LCRL(p,c) writel((c), (p)->membase + AMBA_UARTLCR_L) +#define UART_GET_LCRM(p) readb((p)->membase + AMBA_UARTLCR_M) +#define UART_PUT_LCRM(p,c) writel((c), (p)->membase + AMBA_UARTLCR_M) +#define UART_GET_LCRH(p) readb((p)->membase + AMBA_UARTLCR_H) +#define UART_PUT_LCRH(p,c) writel((c), (p)->membase + AMBA_UARTLCR_H) +#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) +#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) +#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0) + +#define UART_DUMMY_RSR_RX 256 +#define UART_PORT_SIZE 64 + +/* + * On the Integrator platform, the port RTS and DTR are provided by + * bits in the following SC_CTRLS register bits: + * RTS DTR + * UART0 7 6 + * UART1 5 4 + */ +#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) +#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) + +/* + * We wrap our port structure around the generic uart_port. + */ +struct uart_amba_port { + struct uart_port port; + unsigned int dtr_mask; + unsigned int rts_mask; + unsigned int old_status; +}; + +static void ambauart_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + unsigned int cr; + + cr = UART_GET_CR(port); + cr &= ~AMBA_UARTCR_TIE; + UART_PUT_CR(port, cr); +} + +static void ambauart_start_tx(struct uart_port *port, unsigned int tty_start) +{ + unsigned int cr; + + cr = UART_GET_CR(port); + cr |= AMBA_UARTCR_TIE; + UART_PUT_CR(port, cr); +} + +static void ambauart_stop_rx(struct uart_port *port) +{ + unsigned long flags; + unsigned int cr; + + spin_lock_irqsave(&port->lock, flags); + cr = UART_GET_CR(port); + cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE); + UART_PUT_CR(port, cr); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void ambauart_enable_ms(struct uart_port *port) +{ + unsigned long flags; + unsigned int cr; + + spin_lock_irqsave(&port->lock, flags); + cr = UART_GET_CR(port); + cr |= AMBA_UARTCR_MSIE; + UART_PUT_CR(port, cr); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void +#ifdef SUPPORT_SYSRQ +ambauart_rx_chars(struct uart_port *port, struct pt_regs *regs) +#else +ambauart_rx_chars(struct uart_port *port) +#endif +{ + struct tty_struct *tty = port->info->tty; + unsigned int status, ch, rsr, max_count = 256; + + status = UART_GET_FR(port); + while (UART_RX_DATA(status) && max_count--) { + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty->flip.tqueue.routine((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + printk(KERN_WARNING "TTY_DONT_FLIP set\n"); + return; + } + } + + ch = UART_GET_CHAR(port); + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + port->icount.rx++; + + /* + * Note that the error handling code is + * out of the main execution path + */ + rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX; + if (rsr & AMBA_UARTRSR_ANY) { + if (rsr & AMBA_UARTRSR_BE) { + rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE); + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } else if (rsr & AMBA_UARTRSR_PE) + port->icount.parity++; + else if (rsr & AMBA_UARTRSR_FE) + port->icount.frame++; + if (rsr & AMBA_UARTRSR_OE) + port->icount.overrun++; + + rsr &= port->read_status_mask; + + if (rsr & AMBA_UARTRSR_BE) + *tty->flip.flag_buf_ptr = TTY_BREAK; + else if (rsr & AMBA_UARTRSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (rsr & AMBA_UARTRSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; + + if ((rsr & port->ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((rsr & AMBA_UARTRSR_OE) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character + */ + *tty->flip.char_buf_ptr++ = 0; + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + tty->flip.count++; + } + ignore_char: + status = UART_GET_FR(port); + } + tty_flip_buffer_push(tty); + return; +} + +static void ambauart_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + int count; + + if (port->x_char) { + UART_PUT_CHAR(port, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + ambauart_stop_tx(port); + return; + } + + count = port->fifosize >> 1; + do { + UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(port, EVT_WRITE_WAKEUP); + + if (uart_circ_empty(xmit)) + ambauart_stop_tx(port); +} + +static void ambauart_modem_status(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int status, delta; + + UART_PUT_ICR(&uap->port, 0); + + status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY; + + delta = status ^ uap->old_status; + uap->old_status = status; + + if (!delta) + return; + + if (delta & AMBA_UARTFR_DCD) + uart_handle_dcd_change(&uap->port, status & AMBA_UARTFR_DCD); + + if (delta & AMBA_UARTFR_DSR) + uap->port.icount.dsr++; + + if (delta & AMBA_UARTFR_CTS) + uart_handle_cts_change(&uap->port, status & AMBA_UARTFR_CTS); + + wake_up_interruptible(&uap->port.info->delta_msr_wait); +} + +static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + + status = UART_GET_INT_STATUS(port); + do { + if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS)) +#ifdef SUPPORT_SYSRQ + ambauart_rx_chars(port, regs); +#else + ambauart_rx_chars(port); +#endif + if (status & AMBA_UARTIIR_MIS) + ambauart_modem_status(port); + if (status & AMBA_UARTIIR_TIS) + ambauart_tx_chars(port); + + if (pass_counter-- == 0) + break; + + status = UART_GET_INT_STATUS(port); + } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | + AMBA_UARTIIR_TIS)); +} + +static unsigned int ambauart_tx_empty(struct uart_port *port) +{ + return UART_GET_FR(port) & AMBA_UARTFR_BUSY ? 0 : TIOCSER_TEMT; +} + +static unsigned int ambauart_get_mctrl(struct uart_port *port) +{ + unsigned int result = 0; + unsigned int status; + + status = UART_GET_FR(port); + if (status & AMBA_UARTFR_DCD) + result |= TIOCM_CAR; + if (status & AMBA_UARTFR_DSR) + result |= TIOCM_DSR; + if (status & AMBA_UARTFR_CTS) + result |= TIOCM_CTS; + + return result; +} + +static void ambauart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int ctrls = 0, ctrlc = 0; + + if (mctrl & TIOCM_RTS) + ctrlc |= uap->rts_mask; + else + ctrls |= uap->rts_mask; + + if (mctrl & TIOCM_DTR) + ctrlc |= uap->dtr_mask; + else + ctrls |= uap->dtr_mask; + + __raw_writel(ctrls, SC_CTRLS); + __raw_writel(ctrlc, SC_CTRLC); +} + +static void ambauart_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int lcr_h; + + spin_lock_irqsave(&port->lock, flags); + lcr_h = UART_GET_LCRH(port); + if (break_state == -1) + lcr_h |= AMBA_UARTLCR_H_BRK; + else + lcr_h &= ~AMBA_UARTLCR_H_BRK; + UART_PUT_LCRH(port, lcr_h); + spin_unlock_irqrestore(&port->lock, flags); +} + +static int ambauart_startup(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + int retval; + + /* + * Allocate the IRQ + */ + retval = request_irq(port->irq, ambauart_int, 0, "amba", port); + if (retval) + return retval; + + /* + * initialise the old status of the modem signals + */ + uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY; + + /* + * Finally, enable interrupts + */ + UART_PUT_CR(port, AMBA_UARTCR_UARTEN | AMBA_UARTCR_RIE | + AMBA_UARTCR_RTIE); + + return 0; +} + +static void ambauart_shutdown(struct uart_port *port) +{ + /* + * Free the interrupt + */ + free_irq(port->irq, port); + + /* + * disable all interrupts, disable the port + */ + UART_PUT_CR(port, 0); + + /* disable break condition and fifos */ + UART_PUT_LCRH(port, UART_GET_LCRH(port) & + ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN)); +} + +static void +ambauart_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + unsigned int lcr_h, old_cr; + unsigned long flags; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + lcr_h = AMBA_UARTLCR_H_WLEN_5; + break; + case CS6: + lcr_h = AMBA_UARTLCR_H_WLEN_6; + break; + case CS7: + lcr_h = AMBA_UARTLCR_H_WLEN_7; + break; + default: // CS8 + lcr_h = AMBA_UARTLCR_H_WLEN_8; + break; + } + if (cflag & CSTOPB) + lcr_h |= AMBA_UARTLCR_H_STP2; + if (cflag & PARENB) { + lcr_h |= AMBA_UARTLCR_H_PEN; + if (!(cflag & PARODD)) + lcr_h |= AMBA_UARTLCR_H_EPS; + } + if (port->fifosize > 1) + lcr_h |= AMBA_UARTLCR_H_FEN; + + port->read_status_mask = AMBA_UARTRSR_OE; + if (iflag & INPCK) + port->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; + if (iflag & (BRKINT | PARMRK)) + port->read_status_mask |= AMBA_UARTRSR_BE; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (iflag & IGNPAR) + port->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; + if (iflag & IGNBRK) { + port->ignore_status_mask |= AMBA_UARTRSR_BE; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (iflag & IGNPAR) + port->ignore_status_mask |= AMBA_UARTRSR_OE; + } + + /* + * Ignore all characters if CREAD is not set. + */ + if ((cflag & CREAD) == 0) + port->ignore_status_mask |= UART_DUMMY_RSR_RX; + + /* first, disable everything */ + spin_lock_irqsave(&port->lock, flags); + old_cr = UART_GET_CR(port) & ~AMBA_UARTCR_MSIE; + + if (UART_ENABLE_MS(port, cflag)) + old_cr |= AMBA_UARTCR_MSIE; + + UART_PUT_CR(port, 0); + + /* Set baud rate */ + quot -= 1; + UART_PUT_LCRM(port, ((quot & 0xf00) >> 8)); + UART_PUT_LCRL(port, (quot & 0xff)); + + /* + * ----------v----------v----------v----------v----- + * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * ----------^----------^----------^----------^----- + */ + UART_PUT_LCRH(port, lcr_h); + UART_PUT_CR(port, old_cr); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *ambauart_type(struct uart_port *port) +{ + return port->type == PORT_AMBA ? "AMBA" : NULL; +} + +/* + * Release the memory region(s) being used by 'port' + */ +static void ambauart_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, UART_PORT_SIZE); +} + +/* + * Request the memory region(s) being used by 'port' + */ +static int ambauart_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_amba") + != NULL ? 0 : -EBUSY; +} + +/* + * Configure/autoconfigure the port. + */ +static void ambauart_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) { + port->type = PORT_AMBA; + ambauart_request_port(port); + } +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int ambauart_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) + ret = -EINVAL; + if (ser->irq < 0 || ser->irq >= NR_IRQS) + ret = -EINVAL; + if (ser->baud_base < 9600) + ret = -EINVAL; + return ret; +} + +static struct uart_ops amba_pops = { + tx_empty: ambauart_tx_empty, + set_mctrl: ambauart_set_mctrl, + get_mctrl: ambauart_get_mctrl, + stop_tx: ambauart_stop_tx, + start_tx: ambauart_start_tx, + stop_rx: ambauart_stop_rx, + enable_ms: ambauart_enable_ms, + break_ctl: ambauart_break_ctl, + startup: ambauart_startup, + shutdown: ambauart_shutdown, + change_speed: ambauart_change_speed, + type: ambauart_type, + release_port: ambauart_release_port, + request_port: ambauart_request_port, + config_port: ambauart_config_port, + verify_port: ambauart_verify_port, +}; + +static struct uart_amba_port amba_ports[UART_NR] = { + { + port: { + membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), + mapbase: INTEGRATOR_UART0_BASE, + iotype: SERIAL_IO_MEM, + irq: IRQ_UARTINT0, + uartclk: 14745600, + fifosize: 16, + ops: &amba_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 0, + }, + dtr_mask: 1 << 5, + rts_mask: 1 << 4, + }, + { + port: { + membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), + mapbase: INTEGRATOR_UART1_BASE, + iotype: SERIAL_IO_MEM, + irq: IRQ_UARTINT1, + uartclk: 14745600, + fifosize: 16, + ops: &amba_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 1, + }, + dtr_mask: 1 << 7, + rts_mask: 1 << 6, + } +}; + +#ifdef CONFIG_SERIAL_AMBA_CONSOLE + +static void +ambauart_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = &amba_ports[co->index].port; + unsigned int status, old_cr; + int i; + + /* + * First save the CR then disable the interrupts + */ + old_cr = UART_GET_CR(port); + UART_PUT_CR(port, AMBA_UARTCR_UARTEN); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + do { + status = UART_GET_FR(port); + } while (!UART_TX_READY(status)); + UART_PUT_CHAR(port, s[i]); + if (s[i] == '\n') { + do { + status = UART_GET_FR(port); + } while (!UART_TX_READY(status)); + UART_PUT_CHAR(port, '\r'); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the TCR + */ + do { + status = UART_GET_FR(port); + } while (status & AMBA_UARTFR_BUSY); + UART_PUT_CR(port, old_cr); +} + +static kdev_t ambauart_console_device(struct console *co) +{ + return mk_kdev(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + co->index); +} + +static void __init +ambauart_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits) +{ + if (UART_GET_CR(port) & AMBA_UARTCR_UARTEN) { + unsigned int lcr_h, quot; + lcr_h = UART_GET_LCRH(port); + + *parity = 'n'; + if (lcr_h & AMBA_UARTLCR_H_PEN) { + if (lcr_h & AMBA_UARTLCR_H_EPS) + *parity = 'e'; + else + *parity = 'o'; + } + + if ((lcr_h & 0x60) == AMBA_UARTLCR_H_WLEN_7) + *bits = 7; + else + *bits = 8; + + quot = UART_GET_LCRL(port) | UART_GET_LCRM(port) << 8; + *baud = port->uartclk / (16 * (quot + 1)); + } +} + +static int __init ambauart_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 38400; + 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 = &amba_ports[co->index].port; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + ambauart_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct console amba_console = { + name: "ttyAM", + write: ambauart_console_write, + device: ambauart_console_device, + setup: ambauart_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init ambauart_console_init(void) +{ + register_console(&amba_console); +} + +#define AMBA_CONSOLE &amba_console +#else +#define AMBA_CONSOLE NULL +#endif + +static struct uart_driver amba_reg = { + owner: THIS_MODULE, + driver_name: "ttyAM", +#ifdef CONFIG_DEVFS_FS + dev_name: "ttyAM%d", +#else + dev_name: "ttyAM", +#endif + major: SERIAL_AMBA_MAJOR, + minor: SERIAL_AMBA_MINOR, + nr: UART_NR, + cons: AMBA_CONSOLE, +}; + +static int __init ambauart_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: AMBA driver $Revision: 1.37 $\n"); + + ret = uart_register_driver(&amba_reg); + if (ret == 0) { + int i; + + for (i = 0; i < UART_NR; i++) + uart_add_one_port(&amba_reg, &amba_ports[i].port); + } + return ret; +} + +static void __exit ambauart_exit(void) +{ + int i; + + for (i = 0; i < UART_NR; i++) + uart_remove_one_port(&amba_reg, &amba_ports[i].port); + + uart_unregister_driver(&amba_reg); +} + +module_init(ambauart_init); +module_exit(ambauart_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd"); +MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.37 $"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/anakin.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,540 @@ +/* + * linux/drivers/char/anakin.c + * + * Based on driver for AMBA serial ports, by ARM Limited, + * Deep Blue Solutions Ltd., Linus Torvalds and Theodore Ts'o. + * + * Copyright (C) 2001 Aleph One Ltd. for Acunia N.V. + * + * Copyright (C) 2001 Blue Mug, Inc. for Acunia N.V. + * + * 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. + * + * Changelog: + * 20-Apr-2001 TTC Created + * 05-May-2001 W/TTC Updated for serial_core.c + * 27-Jun-2001 jonm Minor changes; add mctrl support, switch to + * SA_INTERRUPT. Works reliably now. No longer requires + * changes to the serial_core API. + * + * $Id: anakin.c,v 1.29 2002/07/22 15:27:32 rmk Exp $ + */ + +#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 UART_NR 5 + +#define SERIAL_ANAKIN_NAME "ttyAN" +#define SERIAL_ANAKIN_MAJOR 204 +#define SERIAL_ANAKIN_MINOR 32 + +static unsigned int txenable[NR_IRQS]; /* Software interrupt register */ + +static inline unsigned int +anakin_in(struct uart_port *port, unsigned int offset) +{ + return __raw_readl(port->base + offset); +} + +static inline void +anakin_out(struct uart_port *port, unsigned int offset, unsigned int value) +{ + __raw_writel(value, port->base + offset); +} + +static void +anakin_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + txenable[port->irq] = 0; +} + +static inline void +anakin_transmit_buffer(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + while (!(anakin_in(port, 0x10) & TXEMPTY)); + anakin_out(port, 0x14, xmit->buf[xmit->tail]); + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); + port->icount.tx++; + + if (uart_circ_empty(xmit)) + anakin_stop_tx(port, 0); +} + +static inline void +anakin_transmit_x_char(struct uart_port *port) +{ + anakin_out(port, 0x14, port->x_char); + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST); + port->icount.tx++; + port->x_char = 0; +} + +static void +anakin_start_tx(struct uart_port *port, unsigned int tty_start) +{ + // is it this... or below + if (!txenable[port->irq]) { + txenable[port->irq] = TXENABLE; + + if ((anakin_in(port, 0x10) & TXEMPTY)) { + anakin_transmit_buffer(port); + } + } +} + +static void +anakin_stop_rx(struct uart_port *port) +{ + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + while (anakin_in(port, 0x10) & RXRELEASE) + anakin_in(port, 0x14); + anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void +anakin_enable_ms(struct uart_port *port) +{ +} + +static inline void +anakin_rx_chars(struct uart_port *port) +{ + unsigned int ch; + struct tty_struct *tty = port->info->tty; + + if (!(anakin_in(port, 0x10) & RXRELEASE)) + return; + + ch = anakin_in(port, 0x14) & 0xff; + + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + *tty->flip.char_buf_ptr++ = ch; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + port->icount.rx++; + tty->flip.count++; + } + tty_flip_buffer_push(tty); +} + +static inline void +anakin_overrun_chars(struct uart_port *port) +{ + unsigned int ch; + + ch = anakin_in(port, 0x14); + port->icount.overrun++; +} + +static inline void +anakin_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + anakin_transmit_x_char(port); + return; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + anakin_stop_tx(port, 0); + return; + } + + anakin_transmit_buffer(port); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(port, EVT_WRITE_WAKEUP); +} + +static void +anakin_int(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status; + struct uart_port *port = dev_id; + + status = anakin_in(port, 0x1c); + + if (status & RX) + anakin_rx_chars(port); + + if (status & OVERRUN) + anakin_overrun_chars(port); + + if (txenable[port->irq] && (status & TX)) + anakin_tx_chars(port); +} + +static unsigned int +anakin_tx_empty(struct uart_port *port) +{ + return anakin_in(port, 0x10) & TXEMPTY ? TIOCSER_TEMT : 0; +} + +static unsigned int +anakin_get_mctrl(struct uart_port *port) +{ + unsigned int status = 0; + + status |= (anakin_in(port, 0x10) & CTS ? TIOCM_CTS : 0); + status |= (anakin_in(port, 0x18) & DCD ? TIOCM_CAR : 0); + status |= (anakin_in(port, 0x18) & DTR ? TIOCM_DTR : 0); + status |= (anakin_in(port, 0x18) & RTS ? TIOCM_RTS : 0); + + return status; +} + +static void +anakin_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + unsigned int status; + + status = anakin_in(port, 0x18); + + if (mctrl & TIOCM_RTS) + status |= RTS; + else + status &= ~RTS; + + if (mctrl & TIOCM_CAR) + status |= DCD; + else + status &= ~DCD; + + anakin_out(port, 0x18, status); +} + +static void +anakin_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int status; + + spin_lock_irqsave(&port->lock, flags); + status = anakin_in(port, 0x20); + + if (break_state == -1) + status |= SETBREAK; + else + status &= ~SETBREAK; + + anakin_out(port, 0x20, status); + spin_unlock_irqrestore(&port->lock, flags); +} + +static int anakin_startup(struct uart_port *port) +{ + int retval; + unsigned int read,write; + + /* + * Allocate the IRQ + */ + retval = request_irq(port->irq, anakin_int, SA_INTERRUPT, + "serial_anakin", port); + if (retval) + return retval; + + /* + * initialise the old status of the modem signals + */ + port->old_status = 0; + + /* + * Finally, disable IRQ and softIRQs for first byte) + */ + txenable[port->irq] = 0; + read = anakin_in(port, 0x18); + write = (read & ~(RTS | DTR | BLOCKRX)) | IRQENABLE; + anakin_out(port, 0x18, write); + + return 0; +} + +static void anakin_shutdown(struct uart_port *port) +{ + /* + * Free the interrupt + */ + free_irq(port->irq, port); + + /* + * disable all interrupts, disable the port + */ + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~IRQENABLE); +} + +static void +anakin_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + unsigned int flags; + + spin_lock_irqsave(&port->lock, flags); + while (!(anakin_in(port, 0x10) & TXEMPTY)); + anakin_out(port, 0x10, (anakin_in(port, 0x10) & ~PRESCALER) + | (quot << 3)); + + //parity always set to none + anakin_out(port, 0x18, anakin_in(port, 0x18) & ~PARITY); + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *anakin_type(struct port *port) +{ + return port->type == PORT_ANAKIN ? "ANAKIN" : NULL; +} + +static struct uart_ops anakin_pops = { + tx_empty: anakin_tx_empty, + set_mctrl: anakin_set_mctrl, + get_mctrl: anakin_get_mctrl, + stop_tx: anakin_stop_tx, + start_tx: anakin_start_tx, + stop_rx: anakin_stop_rx, + enable_ms: anakin_enable_ms, + break_ctl: anakin_break_ctl, + startup: anakin_startup, + shutdown: anakin_shutdown, + change_speed: anakin_change_speed, + type: anakin_type, +}; + +static struct uart_port anakin_ports[UART_NR] = { + { + base: IO_BASE + UART0, + irq: IRQ_UART0, + uartclk: 3686400, + fifosize: 0, + ops: &anakin_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 0, + }, + { + base: IO_BASE + UART1, + irq: IRQ_UART1, + uartclk: 3686400, + fifosize: 0, + ops: &anakin_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 1, + }, + { + base: IO_BASE + UART2, + irq: IRQ_UART2, + uartclk: 3686400, + fifosize: 0, + ops: &anakin_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 2, + }, + { + base: IO_BASE + UART3, + irq: IRQ_UART3, + uartclk: 3686400, + fifosize: 0, + ops: &anakin_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 3, + }, + { + base: IO_BASE + UART4, + irq: IRQ_UART4, + uartclk: 3686400, + fifosize: 0, + ops: &anakin_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 4, + }, +}; + + +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE + +static void +anakin_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = &anakin_ports[co->index]; + unsigned int flags, status, i; + + /* + * First save the status then disable the interrupts + */ + local_irq_save(flags); + status = anakin_in(port, 0x18); + anakin_out(port, 0x18, status & ~IRQENABLE); + local_irq_restore(flags); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + while (!(anakin_in(port, 0x10) & TXEMPTY)); + + /* + * Send the character out. + * If a LF, also do CR... + */ + anakin_out(port, 0x14, *s); + anakin_out(port, 0x18, anakin_in(port, 0x18) | SENDREQUEST); + + if (*s == 10) { + while (!(anakin_in(port, 0x10) & TXEMPTY)); + anakin_out(port, 0x14, 13); + anakin_out(port, 0x18, anakin_in(port, 0x18) + | SENDREQUEST); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the interrupts + */ + while (!(anakin_in(port, 0x10) & TXEMPTY)); + + if (status & IRQENABLE) { + local_irq_save(flags); + anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE); + local_irq_restore(flags); + } +} + +static kdev_t +anakin_console_device(struct console *co) +{ + return mk_kdev(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR + co->index); +} + +/* + * Read the current UART setup. + */ +static void __init +anakin_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) +{ + int paritycode; + + *baud = GETBAUD (anakin_in(port, 0x10) & PRESCALER); + paritycode = GETPARITY(anakin_in(port, 0x18) & PARITY); + switch (paritycode) { + case NONEPARITY: *parity = 'n'; break; + case ODDPARITY: *parity = 'o'; break; + case EVENPARITY: *parity = 'e'; break; + } + *bits = 8; +} + +static int __init +anakin_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = CONFIG_ANAKIN_DEFAULT_BAUDRATE; + int bits = 8; + int parity = '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 = &anakin_ports[co->index]; + + if (options) + uart_parse_options(options, &baud, &parity, &bits); + else + anakin_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits); +} + +static struct console anakin_console = { + name: SERIAL_ANAKIN_NAME, + write: anakin_console_write, + device: anakin_console_device, + setup: anakin_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init +anakin_console_init(void) +{ + register_console(&anakin_console); +} + +#define ANAKIN_CONSOLE &anakin_console +#else +#define ANAKIN_CONSOLE NULL +#endif + +static struct uart_register anakin_reg = { + driver_name: SERIAL_ANAKIN_NAME, + dev_name: SERIAL_ANAKIN_NAME, + major: SERIAL_ANAKIN_MAJOR, + minor: SERIAL_ANAKIN_MINOR, + nr: UART_NR, + cons: ANAKIN_CONSOLE, +}; + +static int __init +anakin_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: Anakin driver $Revision: 1.29 $\n"); + + ret = uart_register_driver(&anakin_reg); + if (ret == 0) { + int i; + + for (i = 0; i < UART_NR; i++) + uart_add_one_port(&anakin_reg, &anakin_ports[i]); + } + return ret; +} + +__initcall(anakin_init); + +MODULE_DESCRIPTION("Anakin serial driver"); +MODULE_AUTHOR("Tak-Shing Chan "); +MODULE_SUPPORTED_DEVICE("ttyAN"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/clps711x.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,629 @@ +/* + * linux/drivers/char/clps711x.c + * + * Driver for CLPS711x serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright 1999 ARM Limited + * Copyright (C) 2000 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 + * 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 + * + * $Id: clps711x.c,v 1.40 2002/07/22 15:27:32 rmk Exp $ + * + */ +#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 + +#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#include + +#define UART_NR 2 + +#ifndef CONFIG_SERIAL_CLPS711X_OLD_NAME +#define SERIAL_CLPS711X_NAME "ttyCL" +#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_NAME "ttyAM" +#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. + */ +#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1) +#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1) +#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1) +#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1) + +#define TX_IRQ(port) ((port)->irq) +#define RX_IRQ(port) ((port)->irq + 1) + +#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR) + +#define tx_enabled(port) ((port)->unused[0]) + +static void +clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + if (tx_enabled(port)) { + disable_irq(TX_IRQ(port)); + tx_enabled(port) = 0; + } +} + +static void +clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start) +{ + if (!tx_enabled(port)) { + enable_irq(TX_IRQ(port)); + tx_enabled(port) = 1; + } +} + +static void clps711xuart_stop_rx(struct uart_port *port) +{ + disable_irq(RX_IRQ(port)); +} + +static void clps711xuart_enable_ms(struct uart_port *port) +{ +} + +static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + struct tty_struct *tty = port->info->tty; + unsigned int status, ch, flg, ignored = 0; + + status = clps_readl(SYSFLG(port)); + while (!(status & SYSFLG_URXFE)) { + ch = clps_readl(UARTDR(port)); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + port->icount.rx++; + + flg = TTY_NORMAL; + + /* + * Note that the error handling code is + * out of the main execution path + */ + if (ch & UART_ANY_ERR) + goto handle_error; + + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; + + error_return: + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + ignore_char: + status = clps_readl(SYSFLG(port)); + } + out: + tty_flip_buffer_push(tty); + return; + + handle_error: + if (ch & UARTDR_PARERR) + port->icount.parity++; + else if (ch & UARTDR_FRMERR) + port->icount.frame++; + if (ch & UARTDR_OVERR) + port->icount.overrun++; + + if (ch & port->ignore_status_mask) { + if (++ignored > 100) + goto out; + goto ignore_char; + } + ch &= port->read_status_mask; + + if (ch & UARTDR_PARERR) + flg = TTY_PARITY; + else if (ch & UARTDR_FRMERR) + flg = TTY_FRAME; + + if (ch & UARTDR_OVERR) { + /* + * CHECK: does overrun affect the current character? + * ASSUMPTION: it does not. + */ + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + ch = 0; + flg = TTY_OVERRUN; + } +#ifdef SUPPORT_SYSRQ + port->sysrq = 0; +#endif + goto error_return; +} + +static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + struct circ_buf *xmit = &port->info->xmit; + int count; + + if (port->x_char) { + clps_writel(port->x_char, UARTDR(port)); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + clps711xuart_stop_tx(port); + return; + } + + count = port->fifosize >> 1; + do { + clps_writel(xmit->buf[xmit->tail], UARTDR(port)); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(port, EVT_WRITE_WAKEUP); + + if (uart_circ_empty(xmit)) + clps711xuart_stop_tx(port); +} + +static unsigned int clps711xuart_tx_empty(struct uart_port *port) +{ + unsigned int status = clps_readl(SYSFLG(port)); + return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT; +} + +static unsigned int clps711xuart_get_mctrl(struct uart_port *port) +{ + unsigned int port_addr; + unsigned int result = 0; + unsigned int status; + + port_addr = SYSFLG(port); + if (port_addr == SYSFLG1) { + status = clps_readl(SYSFLG1); + if (status & SYSFLG1_DCD) + result |= TIOCM_CAR; + if (status & SYSFLG1_DSR) + result |= TIOCM_DSR; + if (status & SYSFLG1_CTS) + result |= TIOCM_CTS; + } + + return result; +} + +static void +clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl) +{ +} + +static void clps711xuart_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int ubrlcr; + + spin_lock_irqsave(&port->lock, flags); + ubrlcr = clps_readl(UBRLCR(port)); + if (break_state == -1) + ubrlcr |= UBRLCR_BREAK; + else + ubrlcr &= ~UBRLCR_BREAK; + clps_writel(ubrlcr, UBRLCR(port)); + spin_unlock_irqrestore(&port->lock, flags); +} + +static int clps711xuart_startup(struct uart_port *port) +{ + unsigned int syscon; + int retval; + + tx_enabled(port) = 1; + + /* + * Allocate the IRQs + */ + retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0, + "clps711xuart_tx", port); + if (retval) + return retval; + + retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0, + "clps711xuart_rx", port); + if (retval) { + free_irq(TX_IRQ(port), port); + return retval; + } + + /* + * enable the port + */ + syscon = clps_readl(SYSCON(port)); + syscon |= SYSCON_UARTEN; + clps_writel(syscon, SYSCON(port)); + + return 0; +} + +static void clps711xuart_shutdown(struct uart_port *port) +{ + unsigned int ubrlcr, syscon; + + /* + * Free the interrupt + */ + free_irq(TX_IRQ(port), port); /* TX interrupt */ + free_irq(RX_IRQ(port), port); /* RX interrupt */ + + /* + * disable the port + */ + syscon = clps_readl(SYSCON(port)); + syscon &= ~SYSCON_UARTEN; + clps_writel(syscon, SYSCON(port)); + + /* + * disable break condition and fifos + */ + ubrlcr = clps_readl(UBRLCR(port)); + ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK); + clps_writel(ubrlcr, UBRLCR(port)); +} + +static void +clps711xuart_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + unsigned int ubrlcr; + unsigned long flags; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + ubrlcr = UBRLCR_WRDLEN5; + break; + case CS6: + ubrlcr = UBRLCR_WRDLEN6; + break; + case CS7: + ubrlcr = UBRLCR_WRDLEN7; + break; + default: // CS8 + ubrlcr = UBRLCR_WRDLEN8; + break; + } + if (cflag & CSTOPB) + ubrlcr |= UBRLCR_XSTOP; + if (cflag & PARENB) { + ubrlcr |= UBRLCR_PRTEN; + if (!(cflag & PARODD)) + ubrlcr |= UBRLCR_EVENPRT; + } + if (port->fifosize > 1) + ubrlcr |= UBRLCR_FIFOEN; + + port->read_status_mask = UARTDR_OVERR; + if (iflag & INPCK) + port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (iflag & IGNPAR) + port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR; + if (iflag & IGNBRK) { + /* + * If we're ignoring parity and break indicators, + * ignore overruns to (for real raw support). + */ + if (iflag & IGNPAR) + port->ignore_status_mask |= UARTDR_OVERR; + } + + quot -= 1; + + /* first, disable everything */ + spin_lock_irqsave(&port->lock, flags); + + clps_writel(ubrlcr | quot, UBRLCR(port)); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *clps711xuart_type(struct uart_port *port) +{ + return port->type == PORT_CLPS711X ? "CLPS711x" : NULL; +} + +/* + * Configure/autoconfigure the port. + */ +static void clps711xuart_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + port->type = PORT_CLPS711X; +} + +static void clps711xuart_release_port(struct uart_port *port) +{ +} + +static int clps711xuart_request_port(struct uart_port *port) +{ + return 0; +} + +static struct uart_ops clps711x_pops = { + tx_empty: clps711xuart_tx_empty, + set_mctrl: clps711xuart_set_mctrl_null, + get_mctrl: clps711xuart_get_mctrl, + stop_tx: clps711xuart_stop_tx, + start_tx: clps711xuart_start_tx, + stop_rx: clps711xuart_stop_rx, + enable_ms: clps711xuart_enable_ms, + break_ctl: clps711xuart_break_ctl, + startup: clps711xuart_startup, + shutdown: clps711xuart_shutdown, + change_speed: clps711xuart_change_speed, + type: clps711xuart_type, + config_port: clps711xuart_config_port, + release_port: clps711xuart_release_port, + request_port: clps711xuart_request_port, +}; + +static struct uart_port clps711x_ports[UART_NR] = { + { + iobase: SYSCON1, + irq: IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ + uartclk: 3686400, + fifosize: 16, + ops: &clps711x_pops, + flags: ASYNC_BOOT_AUTOCONF, + }, + { + iobase: SYSCON2, + irq: IRQ_UTXINT2, /* IRQ_URXINT2 */ + uartclk: 3686400, + fifosize: 16, + ops: &clps711x_pops, + flags: ASYNC_BOOT_AUTOCONF, + } +}; + +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE +/* + * 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. + * + * Note that this is called with interrupts already disabled + */ +static void +clps711xuart_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct uart_port *port = clps711x_ports + co->index; + unsigned int status, syscon; + int i; + + /* + * Ensure that the port is enabled. + */ + syscon = clps_readl(SYSCON(port)); + clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + do { + status = clps_readl(SYSFLG(port)); + } while (status & SYSFLG_UTXFF); + clps_writel(s[i], UARTDR(port)); + if (s[i] == '\n') { + do { + status = clps_readl(SYSFLG(port)); + } while (status & SYSFLG_UTXFF); + clps_writel('\r', UARTDR(port)); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the uart state. + */ + do { + status = clps_readl(SYSFLG(port)); + } while (status & SYSFLG_UBUSY); + + clps_writel(syscon, SYSCON(port)); +} + +static kdev_t clps711xuart_console_device(struct console *co) +{ + return mk_kdev(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR + co->index); +} + +static void __init +clps711xuart_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits) +{ + if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) { + unsigned int ubrlcr, quot; + + ubrlcr = clps_readl(UBRLCR(port)); + + *parity = 'n'; + if (ubrlcr & UBRLCR_PRTEN) { + if (ubrlcr & UBRLCR_EVENPRT) + *parity = 'e'; + else + *parity = 'o'; + } + + if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7) + *bits = 7; + else + *bits = 8; + + quot = ubrlcr & UBRLCR_BAUD_MASK; + *baud = port->uartclk / (16 * (quot + 1)); + } +} + +static int __init clps711xuart_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 38400; + 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. + */ + port = uart_get_console(clps711x_ports, UART_NR, co); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + clps711xuart_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct console clps711x_console = { + name: SERIAL_CLPS711X_NAME, + write: clps711xuart_console_write, + device: clps711xuart_console_device, + setup: clps711xuart_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init clps711xuart_console_init(void) +{ + register_console(&clps711x_console); +} + +#define CLPS711X_CONSOLE &clps711x_console +#else +#define CLPS711X_CONSOLE NULL +#endif + +static struct uart_driver clps711x_reg = { + driver_name: "ttyCL", +#ifdef CONFIG_DEVFS_FS + dev_name: SERIAL_CLPS711X_NAME, +#else + dev_name: SERIAL_CLPS711X_NAME, +#endif + + major: SERIAL_CLPS711X_MAJOR, + minor: SERIAL_CLPS711X_MINOR, + nr: UART_NR, + + cons: CLPS711X_CONSOLE, +}; + +static int __init clps711xuart_init(void) +{ + int ret, i; + + printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.40 $\n"); + + ret = uart_register_driver(&clps711x_reg); + if (ret) + return ret; + + for (i = 0; i < UART_NR; i++) + uart_add_one_port(&clps711x_reg, &clps711x_ports[i]); + + return 0; +} + +static void __exit clps711xuart_exit(void) +{ + int i; + + for (i = 0; i < UART_NR; i++) + uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]); + + uart_unregister_driver(&clps711x_reg); +} + +module_init(clps711xuart_init); +module_exit(clps711xuart_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("Deep Blue Solutions Ltd"); +MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.40 $"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/core.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,2474 @@ +/* + * linux/drivers/char/core.c + * + * Driver core for serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright 1999 ARM Limited + * Copyright (C) 2000-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 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 + * + * $Id: core.c,v 1.91 2002/07/22 15:27:32 rmk Exp $ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for serial_state and serial_icounter_struct */ + +#include +#include +#include +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define DPRINTK(x...) printk(x) +#else +#define DPRINTK(x...) do { } while (0) +#endif + +#ifndef CONFIG_PM +#define pm_access(pm) do { } while (0) +#define pm_unregister(pm) do { } while (0) +#endif + +/* + * This is used to lock changes in serial line configuration. + */ +static DECLARE_MUTEX(port_sem); + +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + +static void uart_change_speed(struct uart_info *info, struct termios *old_termios); +static void uart_wait_until_sent(struct tty_struct *tty, int timeout); + +/* + * This routine is used by the interrupt handler to schedule processing in + * the software interrupt portion of the driver. + */ +void uart_event(struct uart_port *port, int event) +{ + struct uart_info *info = port->info; + + set_bit(0, &info->event); + tasklet_schedule(&info->tlet); +} + +static void uart_stop(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + port->ops->stop_tx(port, 1); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void __uart_start(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + + if (!uart_circ_empty(&info->xmit) && info->xmit.buf && + !tty->stopped && !tty->hw_stopped) + port->ops->start_tx(port, 1); +} + +static void uart_start(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + unsigned long flags; + + pm_access(info->state->pm); + + spin_lock_irqsave(&info->port->lock, flags); + __uart_start(tty); + spin_unlock_irqrestore(&info->port->lock, flags); +} + +static void uart_tasklet_action(unsigned long data) +{ + struct uart_info *info = (struct uart_info *)data; + struct tty_struct *tty; + + tty = info->tty; + if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event)) + return; + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); +} + +static inline void +uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) +{ + unsigned long flags; + unsigned int old; + + spin_lock_irqsave(&port->lock, flags); + old = port->mctrl; + port->mctrl = (old & ~clear) | set; + if (old != port->mctrl) + port->ops->set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); +} + +#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0) +#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear) + +static inline void uart_update_altspeed(struct uart_info *info) +{ + unsigned int flags = info->port->flags & UPF_SPD_MASK; + + if (flags == UPF_SPD_HI) + info->tty->alt_speed = 57600; + if (flags == UPF_SPD_VHI) + info->tty->alt_speed = 115200; + if (flags == UPF_SPD_SHI) + info->tty->alt_speed = 230400; + if (flags == UPF_SPD_WARP) + info->tty->alt_speed = 460800; +} + +/* + * Startup the port. This will be called once per open. All calls + * will be serialised by the global port semaphore. + */ +static int uart_startup(struct uart_info *info, int init_hw) +{ + struct uart_port *port = info->port; + unsigned long page; + int retval = 0; + + if (info->flags & UIF_INITIALIZED) + return 0; + + /* + * Set the TTY IO error marker - we will only clear this + * once we have successfully opened the port. Also set + * up the tty->alt_speed kludge + */ + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + uart_update_altspeed(info); + } + + if (port->type == PORT_UNKNOWN) + return 0; + + /* + * Initialise and allocate the transmit and temporary + * buffer. + */ + if (!info->xmit.buf) { + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + info->xmit.buf = (unsigned char *) page; + info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE; + init_MUTEX(&info->tmpbuf_sem); + uart_circ_clear(&info->xmit); + } + + port->mctrl = 0; + + retval = port->ops->startup(port); + if (retval == 0) { + if (init_hw) { + /* + * Initialise the hardware port settings. + */ + uart_change_speed(info, NULL); + + /* + * Setup the RTS and DTR signals once the + * port is open and ready to respond. + */ + if (info->tty->termios->c_cflag & CBAUD) + uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); + } + + info->flags |= UIF_INITIALIZED; + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + + if (retval && capable(CAP_SYS_ADMIN)) + retval = 0; + + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. Calls to + * uart_shutdown are serialised by port_sem. + */ +static void uart_shutdown(struct uart_info *info) +{ + struct uart_port *port = info->port; + + if (!(info->flags & UIF_INITIALIZED)) + return; + + /* + * Turn off DTR and RTS early. + */ + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + uart_clear_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free + * the irq here so the queue might never be woken up. Note + * that we won't end up waiting on delta_msr_wait again since + * any outstanding file descriptors should be pointing at + * hung_up_tty_fops now. + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * Free the IRQ and disable the port. + */ + port->ops->shutdown(port); + + /* + * Ensure that the IRQ handler isn't running on another CPU. + */ + synchronize_irq(port->irq); + + /* + * Free the transmit buffer page. + */ + if (info->xmit.buf) { + free_page((unsigned long)info->xmit.buf); + info->xmit.buf = NULL; + info->tmpbuf = NULL; + } + + /* + * kill off our tasklet + */ + tasklet_kill(&info->tlet); + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~UIF_INITIALIZED; +} + +static inline +unsigned int uart_calculate_quot(struct uart_info *info, unsigned int baud) +{ + struct uart_port *port = info->port; + unsigned int quot; + + /* Special case: B0 rate */ + if (baud == 0) + baud = 9600; + + /* Old HI/VHI/custom speed handling */ + if (baud == 38400 && + ((port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)) + quot = info->state->custom_divisor; + else + quot = port->uartclk / (16 * baud); + + return quot; +} + +static void +uart_change_speed(struct uart_info *info, struct termios *old_termios) +{ + struct uart_port *port = info->port; + unsigned int quot, cflag, bits, try; + + /* + * If we have no tty, termios, or the port does not exist, + * then we can't set the parameters for this port. + */ + if (!info->tty || !info->tty->termios || port->type == PORT_UNKNOWN) + return; + + /* + * Set flags based on termios cflag + */ + cflag = info->tty->termios->c_cflag; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + bits = 7; + break; + case CS6: + bits = 8; + break; + case CS7: + bits = 9; + break; + default: + bits = 10; + break; // CS8 + } + + if (cflag & CSTOPB) + bits++; + if (cflag & PARENB) + bits++; + + for (try = 0; try < 3; try ++) { + unsigned int baud; + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(info->tty); + quot = uart_calculate_quot(info, baud); + if (quot) + break; + + /* + * Oops, the quotient was zero. Try again with + * the old baud rate if possible. + */ + info->tty->termios->c_cflag &= ~CBAUD; + if (old_termios) { + info->tty->termios->c_cflag |= + (old_termios->c_cflag & CBAUD); + old_termios = NULL; + continue; + } + + /* + * As a last resort, if the quotient is zero, + * default to 9600 bps + */ + info->tty->termios->c_cflag |= B9600; + } + + /* + * The total number of bits to be transmitted in the fifo. + */ + bits = bits * port->fifosize; + + /* + * Figure the timeout to send the above number of bits. + * Add .02 seconds of slop + */ + port->timeout = (HZ * bits) / (port->uartclk / (16 * quot)) + HZ/50; + + if (cflag & CRTSCTS) + info->flags |= UIF_CTS_FLOW; + else + info->flags &= ~UIF_CTS_FLOW; + if (cflag & CLOCAL) + info->flags &= ~UIF_CHECK_CD; + else + info->flags |= UIF_CHECK_CD; + + port->ops->change_speed(port, cflag, info->tty->termios->c_iflag, quot); +} + +static inline void +__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) +{ + unsigned long flags; + + if (!circ->buf) + return; + + spin_lock_irqsave(&port->lock, flags); + if (uart_circ_chars_free(circ) != 0) { + circ->buf[circ->head] = c; + circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1); + } + spin_unlock_irqrestore(&port->lock, flags); +} + +static inline int +__uart_user_write(struct uart_port *port, struct circ_buf *circ, + const unsigned char *buf, int count) +{ + unsigned long flags; + int c, ret = 0; + + if (down_interruptible(&port->info->tmpbuf_sem)) + return -EINTR; + + while (1) { + int c1; + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + + c -= copy_from_user(port->info->tmpbuf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + spin_lock_irqsave(&port->lock, flags); + c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(circ->buf + circ->head, port->info->tmpbuf, c); + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); + spin_unlock_irqrestore(&port->lock, flags); + buf += c; + count -= c; + ret += c; + } + up(&port->info->tmpbuf_sem); + + return ret; +} + +static inline int +__uart_kern_write(struct uart_port *port, struct circ_buf *circ, + const unsigned char *buf, int count) +{ + unsigned long flags; + int c, ret = 0; + + spin_lock_irqsave(&port->lock, flags); + while (1) { + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(circ->buf + circ->head, buf, c); + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); + buf += c; + count -= c; + ret += c; + } + spin_unlock_irqrestore(&port->lock, flags); + + return ret; +} + +static void uart_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct uart_info *info = tty->driver_data; + + if (tty) + __uart_put_char(info->port, &info->xmit, ch); +} + +static void uart_flush_chars(struct tty_struct *tty) +{ + uart_start(tty); +} + +static int +uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, + int count) +{ + struct uart_info *info = tty->driver_data; + int ret; + + if (!tty || !info->xmit.buf) + return 0; + + if (from_user) + ret = __uart_user_write(info->port, &info->xmit, buf, count); + else + ret = __uart_kern_write(info->port, &info->xmit, buf, count); + + uart_start(tty); + return ret; +} + +static int uart_write_room(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + + return uart_circ_chars_free(&info->xmit); +} + +static int uart_chars_in_buffer(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + + return uart_circ_chars_pending(&info->xmit); +} + +static void uart_flush_buffer(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + unsigned long flags; + + DPRINTK("uart_flush_buffer(%d) called\n", + MINOR(tty->device) - tty->driver.minor_start); + + spin_lock_irqsave(&info->port->lock, flags); + uart_circ_clear(&info->xmit); + spin_unlock_irqrestore(&info->port->lock, flags); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void uart_send_xchar(struct tty_struct *tty, char ch) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + unsigned long flags; + + if (port->ops->send_xchar) + port->ops->send_xchar(port, ch); + else { + port->x_char = ch; + if (ch) { + spin_lock_irqsave(&port->lock, flags); + port->ops->start_tx(port, 0); + spin_unlock_irqrestore(&port->lock, flags); + } + } +} + +static void uart_throttle(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + + if (I_IXOFF(tty)) + uart_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) + uart_clear_mctrl(info->port, TIOCM_RTS); +} + +static void uart_unthrottle(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + + if (I_IXOFF(tty)) { + if (port->x_char) + port->x_char = 0; + else + uart_send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) + uart_set_mctrl(port, TIOCM_RTS); +} + +static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) +{ + struct uart_state *state = info->state; + struct uart_port *port = info->port; + struct serial_struct tmp; + + memset(&tmp, 0, sizeof(tmp)); + tmp.type = port->type; + tmp.line = port->line; + tmp.port = port->iobase; + if (HIGH_BITS_OFFSET) + tmp.port_high = port->iobase >> HIGH_BITS_OFFSET; + tmp.irq = port->irq; + tmp.flags = port->flags | info->flags; + tmp.xmit_fifo_size = port->fifosize; + tmp.baud_base = port->uartclk / 16; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = state->custom_divisor; + tmp.hub6 = port->hub6; + tmp.io_type = port->iotype; + tmp.iomem_reg_shift = port->regshift; + tmp.iomem_base = (void *)port->mapbase; + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int +uart_set_info(struct uart_info *info, struct serial_struct *newinfo) +{ + struct serial_struct new_serial; + struct uart_state *state = info->state; + struct uart_port *port = info->port; + unsigned long new_port; + unsigned int change_irq, change_port, old_flags; + unsigned int old_custom_divisor; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + new_port = new_serial.port; + if (HIGH_BITS_OFFSET) + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; + + new_serial.irq = irq_cannonicalize(new_serial.irq); + + /* + * This semaphore protects state->count. It is also + * very useful to prevent opens. Also, take the + * port configuration semaphore to make sure that a + * module insertion/removal doesn't change anything + * under us. + */ + down(&port_sem); + + change_irq = new_serial.irq != port->irq; + + /* + * Since changing the 'type' of the port changes its resource + * allocations, we should treat type changes the same as + * IO port changes. + */ + change_port = new_port != port->iobase || + (unsigned long)new_serial.iomem_base != port->mapbase || + new_serial.hub6 != port->hub6 || + new_serial.io_type != port->iotype || + new_serial.iomem_reg_shift != port->regshift || + new_serial.type != port->type; + + old_flags = port->flags; + old_custom_divisor = state->custom_divisor; + + if (!capable(CAP_SYS_ADMIN)) { + retval = -EPERM; + if (change_irq || change_port || + (new_serial.baud_base != port->uartclk / 16) || + (new_serial.close_delay != state->close_delay) || + (new_serial.closing_wait != state->closing_wait) || + (new_serial.xmit_fifo_size != port->fifosize) || + (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) + goto exit; + port->flags = ((port->flags & ~UPF_USR_MASK) | + (new_serial.flags & UPF_USR_MASK)); + state->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + /* + * Ask the low level driver to verify the settings. + */ + if (port->ops->verify_port) + retval = port->ops->verify_port(port, &new_serial); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || + (new_serial.baud_base < 9600)) + retval = -EINVAL; + + if (retval) + goto exit; + + if (change_port || change_irq) { + retval = -EBUSY; + + /* + * Make sure that we are the sole user of this port. + */ + if (state->count > 1 || info->blocked_open != 0) + goto exit; + + /* + * We need to shutdown the serial port at the old + * port/type/irq combination. + */ + uart_shutdown(info); + } + + if (change_port) { + unsigned long old_iobase, old_mapbase; + unsigned int old_type, old_iotype, old_hub6, old_shift; + + old_iobase = port->iobase; + old_mapbase = port->mapbase; + old_type = port->type; + old_hub6 = port->hub6; + old_iotype = port->iotype; + old_shift = port->regshift; + + /* + * Free and release old regions + */ + if (old_type != PORT_UNKNOWN) + port->ops->release_port(port); + + port->iobase = new_port; + port->type = new_serial.type; + port->hub6 = new_serial.hub6; + port->iotype = new_serial.io_type; + port->regshift = new_serial.iomem_reg_shift; + port->mapbase = (unsigned long)new_serial.iomem_base; + + /* + * Claim and map the new regions + */ + if (port->type != PORT_UNKNOWN) + retval = port->ops->request_port(port); + + /* + * If we fail to request resources for the + * new port, try to restore the old settings. + */ + if (retval && old_type != PORT_UNKNOWN) { + port->iobase = old_iobase; + port->type = old_type; + port->hub6 = old_hub6; + port->iotype = old_iotype; + port->regshift = old_shift; + port->mapbase = old_mapbase; + retval = port->ops->request_port(port); + /* + * If we failed to restore the old settings, + * we fail like this. + */ + if (retval) + port->type = PORT_UNKNOWN; + + /* + * We failed anyway. + */ + retval = -EBUSY; + } + } + + port->irq = new_serial.irq; + port->uartclk = new_serial.baud_base * 16; + port->flags = new_serial.flags & UPF_FLAGS; + state->custom_divisor = new_serial.custom_divisor; + state->close_delay = new_serial.close_delay * HZ / 100; + state->closing_wait = new_serial.closing_wait * HZ / 100; + port->fifosize = new_serial.xmit_fifo_size; + info->tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0; + + check_and_exit: + retval = 0; + if (port->type == PORT_UNKNOWN) + goto exit; + if (info->flags & UIF_INITIALIZED) { + if (((old_flags ^ port->flags) & UPF_SPD_MASK) || + old_custom_divisor != state->custom_divisor) { + uart_update_altspeed(info); + uart_change_speed(info, NULL); + } + } else + retval = uart_startup(info, 1); + exit: + up(&port_sem); + return retval; +} + + +/* + * uart_get_lsr_info - get line status register info + */ +static int uart_get_lsr_info(struct uart_info *info, unsigned int *value) +{ + struct uart_port *port = info->port; + unsigned int result; + + result = port->ops->tx_empty(port); + + /* + * If we're about to load something into the transmit + * register, we'll pretend the transmitter isn't empty to + * avoid a race condition (depending on when the transmit + * interrupt happens). + */ + if (info->port->x_char || + ((uart_circ_chars_pending(&info->xmit) > 0) && + !info->tty->stopped && !info->tty->hw_stopped)) + result &= ~TIOCSER_TEMT; + + return put_user(result, value); +} + +static int uart_get_modem_info(struct uart_port *port, unsigned int *value) +{ + unsigned int result = port->mctrl; + + result |= port->ops->get_mctrl(port); + + return put_user(result, value); +} + +static int +uart_set_modem_info(struct uart_port *port, unsigned int cmd, + unsigned int *value) +{ + unsigned int arg, set, clear; + int ret = 0; + + if (get_user(arg, value)) + return -EFAULT; + + set = clear = 0; + switch (cmd) { + case TIOCMBIS: + set = arg; + break; + case TIOCMBIC: + clear = arg; + break; + case TIOCMSET: + set = arg; + clear = ~arg; + break; + default: + ret = -EINVAL; + break; + } + if (ret == 0) + uart_update_mctrl(port, set, clear); + return ret; +} + +static void uart_break_ctl(struct tty_struct *tty, int break_state) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + + BUG_ON(!kernel_locked()); + + if (port->type != PORT_UNKNOWN) + port->ops->break_ctl(port, break_state); +} + +static int uart_do_autoconfig(struct uart_info *info) +{ + struct uart_port *port = info->port; + int flags, ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* + * Take the 'count' lock. This prevents count + * from incrementing, and hence any extra opens + * of the port while we're auto-configging. + */ + if (down_interruptible(&port_sem)) + return -ERESTARTSYS; + + ret = -EBUSY; + if (info->state->count == 1 && info->blocked_open == 0) { + uart_shutdown(info); + + /* + * If we already have a port type configured, + * we must release its resources. + */ + if (port->type != PORT_UNKNOWN) + port->ops->release_port(port); + + flags = UART_CONFIG_TYPE; + if (port->flags & UPF_AUTO_IRQ) + flags |= UART_CONFIG_IRQ; + + /* + * This will claim the ports resources if + * a port is found. + */ + port->ops->config_port(port, flags); + + ret = uart_startup(info, 1); + } + up(&port_sem); + return ret; +} + +static int +uart_wait_modem_status(struct uart_info *info, unsigned long arg) +{ + struct uart_port *port = info->port; + DECLARE_WAITQUEUE(wait, current); + struct uart_icount cprev, cnow; + int ret; + + /* + * note the counters on entry + */ + spin_lock_irq(&port->lock); + memcpy(&cprev, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + /* + * Force modem status interrupts on + */ + port->ops->enable_ms(port); + + add_wait_queue(&info->delta_msr_wait, &wait); + for (;;) { + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + set_current_state(TASK_INTERRUPTIBLE); + + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + ret = 0; + break; + } + + schedule(); + + /* see if a signal did it */ + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + cprev = cnow; + } + + current->state = TASK_RUNNING; + remove_wait_queue(&info->delta_msr_wait, &wait); + + return ret; +} + +/* + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + */ +static int +uart_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct uart_info *info = tty->driver_data; + struct serial_icounter_struct icount; + struct uart_icount cnow; + int ret = -ENOIOCTLCMD; + + BUG_ON(!kernel_locked()); + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && + (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TIOCMGET: + ret = uart_get_modem_info(info->port, + (unsigned int *)arg); + break; + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + ret = uart_set_modem_info(info->port, cmd, + (unsigned int *)arg); + break; + + case TIOCGSERIAL: + ret = uart_get_info(info, (struct serial_struct *)arg); + break; + + case TIOCSSERIAL: + ret = uart_set_info(info, (struct serial_struct *)arg); + break; + + case TIOCSERCONFIG: + ret = uart_do_autoconfig(info); + break; + + case TIOCSERGETLSR: /* Get line status register */ + ret = uart_get_lsr_info(info, (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 for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: + ret = uart_wait_modem_status(info, arg); + break; + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + spin_lock_irq(&info->port->lock); + memcpy(&cnow, &info->port->icount, + sizeof(struct uart_icount)); + spin_unlock_irq(&info->port->lock); + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + ret = copy_to_user((void *)arg, &icount, sizeof(icount)) + ? -EFAULT : 0; + break; + + case TIOCSERGWILD: /* obsolete */ + case TIOCSERSWILD: /* obsolete */ + ret = 0; + break; + + default: { + struct uart_port *port = info->port; + if (port->ops->ioctl) + ret = port->ops->ioctl(port, cmd, arg); + break; + } + } + return ret; +} + +static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct uart_info *info = tty->driver_data; + unsigned long flags; + unsigned int cflag = tty->termios->c_cflag; + + BUG_ON(!kernel_locked()); + + /* + * These are the bits that are used to setup various + * flags in the low level driver. + */ +#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + if ((cflag ^ old_termios->c_cflag) == 0 && + RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) + return; + + uart_change_speed(info, old_termios); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) + uart_clear_mctrl(info->port, TIOCM_RTS | TIOCM_DTR); + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { + unsigned int mask = TIOCM_DTR; + if (!(cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) + mask |= TIOCM_RTS; + uart_set_mctrl(info->port, mask); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { + spin_lock_irqsave(&info->port->lock, flags); + tty->hw_stopped = 0; + __uart_start(tty); + spin_unlock_irqrestore(&info->port->lock, flags); + } + +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif +} + +/* + * In 2.4.5, calls to this will be serialized via the BKL in + * linux/drivers/char/tty_io.c:tty_release() + * linux/drivers/char/tty_io.c:do_tty_handup() + */ +static void uart_close(struct tty_struct *tty, struct file *filp) +{ + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + struct uart_state *state; + unsigned long flags; + + BUG_ON(!kernel_locked()); + + if (!info) + return; + + state = info->state; + + DPRINTK("uart_close() called\n"); + + /* + * This is safe, as long as the BKL exists in + * do_tty_hangup(), and we're protected by the BKL. + */ + if (tty_hung_up_p(filp)) + goto done; + + spin_lock_irqsave(&info->port->lock, flags); + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("uart_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for %s%d: %d\n", + tty->driver.name, info->port->line, state->count); + state->count = 0; + } + if (state->count) { + spin_unlock_irqrestore(&info->port->lock, flags); + goto done; + } + + /* + * The UIF_CLOSING flag protects us against further opens + * of this port. + */ + info->flags |= UIF_CLOSING; + spin_unlock_irqrestore(&info->port->lock, flags); + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->state->closing_wait != USF_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->state->closing_wait); + + /* + * At this point, we stop accepting input. To do this, we + * disable the receive line status interrupts. + */ + if (info->flags & UIF_INITIALIZED) { + port->ops->stop_rx(port); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + uart_wait_until_sent(tty, port->timeout); + } + down(&port_sem); + uart_shutdown(info); + up(&port_sem); + uart_flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + if (info->state->close_delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(info->state->close_delay); + set_current_state(TASK_RUNNING); + } + } else { +#ifdef CONFIG_PM + /* + * Put device into D3 state. + */ + pm_send(info->state->pm, PM_SUSPEND, (void *)3); +#else + if (port->ops->pm) + port->ops->pm(port, 3, 0); +#endif + } + + /* + * Wake up anyone trying to open this port. + */ + info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CLOSING); + wake_up_interruptible(&info->open_wait); + + done: + if (drv->owner) + __MOD_DEC_USE_COUNT(drv->owner); +} + +static void uart_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct uart_info *info = tty->driver_data; + struct uart_port *port = info->port; + unsigned long char_time, expire; + + BUG_ON(!kernel_locked()); + + if (port->type == PORT_UNKNOWN || port->fifosize == 0) + return; + + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (port->timeout - HZ/50) / port->fifosize; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than port->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*port->timeout. + */ + if (timeout == 0 || timeout > 2 * port->timeout) + timeout = 2 * port->timeout; + + expire = jiffies + timeout; + + DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n", + port->line, jiffies, expire); + + /* + * Check whether the transmitter is empty every 'char_time'. + * 'timeout' / 'expire' give us the maximum amount of time + * we wait. + */ + while (!port->ops->tx_empty(port)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (time_after(jiffies, expire)) + break; + } + set_current_state(TASK_RUNNING); /* might not be needed */ +} + +/* + * This is called with the BKL held in + * linux/drivers/char/tty_io.c:do_tty_hangup() + * We're called from the eventd thread, so we can sleep for + * a _short_ time only. + */ +static void uart_hangup(struct tty_struct *tty) +{ + struct uart_info *info = tty->driver_data; + struct uart_state *state = info->state; + + BUG_ON(!kernel_locked()); + + uart_flush_buffer(tty); + down(&port_sem); + if (info->flags & UIF_CLOSING) { + up(&port_sem); + return; + } + uart_shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~UIF_NORMAL_ACTIVE; + info->tty = NULL; + up(&port_sem); + wake_up_interruptible(&info->open_wait); +} + +/* + * Copy across the serial console cflag setting into the termios settings + * for the initial open of the port. This allows continuity between the + * kernel settings, and the settings init adopts when it opens the port + * for the first time. + */ +static void uart_update_termios(struct uart_info *info) +{ + struct tty_struct *tty = info->tty; + +#ifdef CONFIG_SERIAL_CORE_CONSOLE + struct console *c = info->port->cons; + + if (c && c->cflag && c->index == info->port->line) { + tty->termios->c_cflag = c->cflag; + c->cflag = 0; + } +#endif + + /* + * If the device failed to grab its irq resources, + * or some other error occurred, don't try to talk + * to the port hardware. + */ + if (!(tty->flags & (1 << TTY_IO_ERROR))) { + /* + * Make termios settings take effect. + */ + uart_change_speed(info, NULL); + + /* + * And finally enable the RTS and DTR signals. + */ + if (tty->termios->c_cflag & CBAUD) + uart_set_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + } +} + +static int +uart_block_til_ready(struct file *filp, struct uart_info *info) +{ + DECLARE_WAITQUEUE(wait, current); + struct uart_state *state = info->state; + struct uart_port *port = info->port; + + info->blocked_open++; + state->count--; + + add_wait_queue(&info->open_wait, &wait); + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + + /* + * If we have been hung up, tell userspace/restart open. + */ + if (tty_hung_up_p(filp)) + break; + + /* + * If the device is in the middle of being closed, block + * until it's done. We will need to re-initialise the + * port. Hmm, is it legal to block a non-blocking open? + */ + if (info->flags & UIF_CLOSING) + goto wait; + + /* + * If the port has been closed, tell userspace/restart open. + */ + if (!(info->flags & UIF_INITIALIZED)) + break; + + /* + * If non-blocking mode is set, or CLOCAL mode is set, + * we don't want to wait for the modem status lines to + * indicate that the port is ready. + * + * Also, if the port is not enabled/configured, we want + * to allow the open to succeed here. Note that we will + * have set TTY_IO_ERROR for a non-existant port. + */ + if ((filp->f_flags & O_NONBLOCK) || + (info->tty->termios->c_cflag & CLOCAL) || + (info->tty->flags & (1 << TTY_IO_ERROR))) { + break; + } + + /* + * Set DTR to allow modem to know we're waiting. Do + * not set RTS here - we want to make sure we catch + * the data from the modem. + */ + if (info->tty->termios->c_cflag & CBAUD) + uart_set_mctrl(info->port, TIOCM_DTR); + + /* + * and wait for the carrier to indicate that the + * modem is ready for us. + */ + if (port->ops->get_mctrl(port) & TIOCM_CAR) + break; + + wait: + schedule(); + + if (signal_pending(current)) + break; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&info->open_wait, &wait); + + state->count++; + info->blocked_open--; + + if (signal_pending(current)) + return -ERESTARTSYS; + + if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED)) + return (port->flags & UPF_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + + return 0; +} + +static struct uart_info *uart_get(struct uart_driver *drv, int line) +{ + struct uart_state *state = drv->state + line; + struct uart_info *info = NULL; + + down(&port_sem); + if (!state->port) + goto out; + + state->count++; + info = state->info; + + if (!info) { + info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); + if (info) { + memset(info, 0, sizeof(struct uart_info)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->delta_msr_wait); + + /* + * Link the info into the other structures. + */ + info->port = state->port; + info->state = state; + state->port->info = info; + + tasklet_init(&info->tlet, uart_tasklet_action, + (unsigned long)info); + state->info = info; + } else + state->count--; + } + + out: + up(&port_sem); + return info; +} + +/* + * In 2.4.5, calls to uart_open are serialised by the BKL in + * linux/fs/devices.c:chrdev_open() + * Note that if this fails, then uart_close() _will_ be called. + * + * In time, we want to scrap the "opening nonpresent ports" + * behaviour and implement an alternative way for setserial + * to set base addresses/ports/types. This will allow us to + * get rid of a certain amount of extra tests. + */ +static int uart_open(struct tty_struct *tty, struct file *filp) +{ + struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; + struct uart_info *info; + int retval, line = minor(tty->device) - tty->driver.minor_start; + + BUG_ON(!kernel_locked()); + + DPRINTK("uart_open(%d) called\n", line); + + /* + * tty->driver.num won't change, so we won't fail here with + * tty->driver_data set to something non-NULL (and therefore + * we won't get caught by uart_close()). + */ + retval = -ENODEV; + if (line >= tty->driver.num) + goto fail; + + /* + * If we fail to increment the module use count, we can't have + * any other users of this tty (since this implies that the module + * is about to be unloaded). Therefore, it is safe to set + * tty->driver_data to be NULL, so uart_close() doesn't bite us. + */ + if (!try_inc_mod_count(drv->owner)) { + tty->driver_data = NULL; + goto fail; + } + + /* + * FIXME: This one isn't fun. We can't guarantee that the tty isn't + * already in open, nor can we guarantee the state of tty->driver_data + */ + info = uart_get(drv, line); + retval = -ENOMEM; + if (!info) { + if (tty->driver_data) + goto fail; + else + goto out; + } + + /* + * Once we set tty->driver_data here, we are guaranteed that + * uart_close() will decrement the driver module use count. + * Any failures from here onwards should not touch the count. + */ + tty->driver_data = info; + info->tty = tty; + info->tty->low_latency = (info->port->flags & UPF_LOW_LATENCY) ? 1 : 0; + + /* + * If the port is in the middle of closing, bail out now. + */ + if (tty_hung_up_p(filp) || (info->flags & UIF_CLOSING)) { + wait_event_interruptible(info->open_wait, + !(info->flags & UIF_CLOSING)); + retval = (info->port->flags & UPF_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS; + goto fail; + } + + /* + * Make sure the device is in D0 state. + */ + if (info->state->count == 1) { +#ifdef CONFIG_PM + pm_send(info->state->pm, PM_RESUME, (void *)0); +#else + struct uart_port *port = info->port; + if (port->ops->pm) + port->ops->pm(port, 0, 3); +#endif + } + + /* + * Start up the serial port. We have this semaphore here to + * prevent uart_startup or uart_shutdown being re-entered if + * we sleep while requesting an IRQ. + */ + down(&port_sem); + retval = uart_startup(info, 0); + up(&port_sem); + if (retval) + goto fail; + + /* + * Wait until the port is ready. + */ + retval = uart_block_til_ready(filp, info); + + /* + * If this is the first open to succeed, adjust things to suit. + */ + if (retval == 0 && !(info->flags & UIF_NORMAL_ACTIVE)) { + info->flags |= UIF_NORMAL_ACTIVE; + + uart_update_termios(info); + } + + return retval; + + out: + if (drv->owner) + __MOD_DEC_USE_COUNT(drv->owner); + fail: + return retval; +} + +#ifdef CONFIG_PROC_FS + +static const char *uart_type(struct uart_port *port) +{ + const char *str = NULL; + + if (port->ops->type) + str = port->ops->type(port); + + if (!str) + str = "unknown"; + + return str; +} + +static int uart_line_info(char *buf, struct uart_driver *drv, int i) +{ + struct uart_state *state = drv->state + i; + struct uart_port *port = state->port; + char stat_buf[32]; + unsigned int status; + int ret; + + if (!port) + return 0; + + ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d", + port->line, uart_type(port), + port->iobase, port->irq); + + if (port->type == PORT_UNKNOWN) { + strcat(buf, "\n"); + return ret + 1; + } + + status = port->ops->get_mctrl(port); + + ret += sprintf(buf + ret, " tx:%d rx:%d", + port->icount.tx, port->icount.rx); + if (port->icount.frame) + ret += sprintf(buf + ret, " fe:%d", + port->icount.frame); + if (port->icount.parity) + ret += sprintf(buf + ret, " pe:%d", + port->icount.parity); + if (port->icount.brk) + ret += sprintf(buf + ret, " brk:%d", + port->icount.brk); + if (port->icount.overrun) + ret += sprintf(buf + ret, " oe:%d", + port->icount.overrun); + +#define INFOBIT(bit,str) \ + if (port->mctrl & (bit)) \ + strncat(stat_buf, (str), sizeof(stat_buf) - \ + strlen(stat_buf) - 2) +#define STATBIT(bit,str) \ + if (status & (bit)) \ + strncat(stat_buf, (str), sizeof(stat_buf) - \ + strlen(stat_buf) - 2) + + stat_buf[0] = '\0'; + stat_buf[1] = '\0'; + INFOBIT(TIOCM_RTS, "|RTS"); + STATBIT(TIOCM_CTS, "|CTS"); + INFOBIT(TIOCM_DTR, "|DTR"); + STATBIT(TIOCM_DSR, "|DSR"); + STATBIT(TIOCM_CAR, "|CD"); + STATBIT(TIOCM_RNG, "|RI"); + if (stat_buf[0]) + stat_buf[0] = ' '; + strcat(stat_buf, "\n"); + + ret += sprintf(buf + ret, stat_buf); + return ret; +} + +static int uart_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct tty_driver *ttydrv = data; + struct uart_driver *drv = ttydrv->driver_state; + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", + "", "", ""); + for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) { + l = uart_line_info(page + len, drv, i); + len += l; + if (len + begin > off + count) + goto done; + if (len + begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; + done: + if (off >= len + begin) + return 0; + *start = page + (off - begin); + return (count < begin + len - off) ? count : (begin + len - off); +} +#endif + +#ifdef CONFIG_SERIAL_CORE_CONSOLE +/* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ +struct uart_port * __init +uart_get_console(struct uart_port *ports, int nr, struct console *co) +{ + int idx = co->index; + + if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 && + ports[idx].membase == NULL)) + for (idx = 0; idx < nr; idx++) + if (ports[idx].iobase != 0 || + ports[idx].membase != NULL) + break; + + co->index = idx; + + return ports + idx; +} + +/** + * uart_parse_options - Parse serial port baud/parity/bits/flow contro. + * @options: pointer to option string + * @baud: pointer to an 'int' variable for the baud rate. + * @parity: pointer to an 'int' variable for the parity. + * @bits: pointer to an 'int' variable for the number of data bits. + * @flow: pointer to an 'int' variable for the flow control character. + * + * uart_parse_options decodes a string containing the serial console + * options. The format of the string is , + * eg: 115200n8r + */ +void __init +uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) +{ + char *s = options; + + *baud = simple_strtoul(s, NULL, 10); + while (*s >= '0' && *s <= '9') + s++; + if (*s) + *parity = *s++; + if (*s) + *bits = *s++ - '0'; + if (*s) + *flow = *s; +} + +struct baud_rates { + unsigned int rate; + unsigned int cflag; +}; + +static struct baud_rates baud_rates[] = { + { 921600, B921600 }, + { 460800, B460800 }, + { 230400, B230400 }, + { 115200, B115200 }, + { 57600, B57600 }, + { 38400, B38400 }, + { 19200, B19200 }, + { 9600, B9600 }, + { 4800, B4800 }, + { 2400, B2400 }, + { 1200, B1200 }, + { 0, B38400 } +}; + +/** + * uart_set_options - setup the serial console parameters + * @port: pointer to the serial ports uart_port structure + * @co: console pointer + * @baud: baud rate + * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) + * @bits: number of data bits + * @flow: flow control character - 'r' (rts) + */ +int __init +uart_set_options(struct uart_port *port, struct console *co, + int baud, int parity, int bits, int flow) +{ + unsigned int cflag = CREAD | HUPCL | CLOCAL; + unsigned int quot; + int i; + + /* + * Construct a cflag setting. + */ + for (i = 0; baud_rates[i].rate; i++) + if (baud_rates[i].rate <= baud) + break; + + cflag |= baud_rates[i].cflag; + + if (bits == 7) + cflag |= CS7; + else + cflag |= CS8; + + switch (parity) { + case 'o': case 'O': + cflag |= PARODD; + /*fall through*/ + case 'e': case 'E': + cflag |= PARENB; + break; + } + + if (flow == 'r') + cflag |= CRTSCTS; + + co->cflag = cflag; + quot = (port->uartclk / (16 * baud)); + port->ops->change_speed(port, cflag, 0, quot); + + return 0; +} + +extern void ambauart_console_init(void); +extern void anakin_console_init(void); +extern void clps711xuart_console_init(void); +extern void rs285_console_init(void); +extern void sa1100_rs_console_init(void); +extern void serial8250_console_init(void); +extern void uart00_console_init(void); + +/* + * Central "initialise all serial consoles" container. Needs to be killed. + */ +void __init uart_console_init(void) +{ +#ifdef CONFIG_SERIAL_AMBA_CONSOLE + ambauart_console_init(); +#endif +#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE + anakin_console_init(); +#endif +#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE + clps711xuart_console_init(); +#endif +#ifdef CONFIG_SERIAL_21285_CONSOLE + rs285_console_init(); +#endif +#ifdef CONFIG_SERIAL_SA1100_CONSOLE + sa1100_rs_console_init(); +#endif +#ifdef CONFIG_SERIAL_8250_CONSOLE + serial8250_console_init(); +#endif +#ifdef CONFIG_SERIAL_UART00_CONSOLE + uart00_console_init(); +#endif +} +#endif /* CONFIG_SERIAL_CORE_CONSOLE */ + +#ifdef CONFIG_PM +/* + * Serial port power management. + * + * This is pretty coarse at the moment - either all on or all off. We + * should probably some day do finer power management here some day. + * + * We don't actually save any state; the serial driver already has the + * state held internally to re-setup the port when we come out of D3. + */ +static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate) +{ + struct uart_port *port; + struct uart_ops *ops; + int running = state->info && + state->info->flags & UIF_INITIALIZED; + + down(&port_sem); + + if (!state->port || state->port->type == PORT_UNKNOWN) { + up(&port_sem); + return 0; + } + + port = state->port; + ops = port->ops; + + DPRINTK("pm: %08x: %d -> %d, %srunning\n", + port->iobase, dev->state, pm_state, running ? "" : "not "); + + if (pm_state == 0) { + if (ops->pm) + ops->pm(port, pm_state, oldstate); + if (running) { + /* + * The port lock isn't taken here - + * the port isn't initialised. + */ + ops->set_mctrl(port, 0); + ops->startup(port); + uart_change_speed(state->info, NULL); + spin_lock_irq(&port->lock); + ops->set_mctrl(port, port->mctrl); + ops->start_tx(port, 0); + spin_unlock_irq(&port->lock); + } + + /* + * Re-enable the console device after suspending. + */ + if (port->cons && port->cons->index == port->line) + port->cons->flags |= CON_ENABLED; + } else if (pm_state == 1) { + if (ops->pm) + ops->pm(port, pm_state, oldstate); + } else { + /* + * Disable the console device before suspending. + */ + if (port->cons && port->cons->index == port->line) + port->cons->flags &= ~CON_ENABLED; + + if (running) { + spin_lock_irq(&port->lock); + ops->stop_tx(port, 0); + ops->set_mctrl(port, 0); + spin_unlock_irq(&port->lock); + ops->stop_rx(port); + ops->shutdown(port); + } + if (ops->pm) + ops->pm(port, pm_state, oldstate); + } + up(&port_sem); + + return 0; +} + +/* + * Wakeup support. + */ +static int uart_pm_set_wakeup(struct uart_state *state, int data) +{ + int err = 0; + + if (state->port->ops->set_wake) + err = state->port->ops->set_wake(state->port, data); + + return err; +} + +static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct uart_state *state = dev->data; + int err = 0; + + switch (rqst) { + case PM_SUSPEND: + case PM_RESUME: + err = uart_pm_set_state(state, (int)data, dev->state); + break; + + case PM_SET_WAKEUP: + err = uart_pm_set_wakeup(state, (int)data); + break; + } + return err; +} +#endif + +static inline void +uart_report_port(struct uart_driver *drv, struct uart_port *port) +{ + printk("%s%d at ", drv->dev_name, port->line); + switch (port->iotype) { + case UPIO_PORT: + printk("I/O 0x%x", port->iobase); + break; + case UPIO_HUB6: + printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6); + break; + case UPIO_MEM: + printk("MMIO 0x%lx", port->mapbase); + break; + } + printk(" (irq = %d) is a %s\n", port->irq, uart_type(port)); +} + +static void +__uart_register_port(struct uart_driver *drv, struct uart_state *state, + struct uart_port *port) +{ + unsigned int flags; + + state->port = port; + + spin_lock_init(&port->lock); + port->type = PORT_UNKNOWN; + port->cons = drv->cons; + port->info = state->info; + + /* + * If there isn't a port here, don't do anything further. + */ + if (!port->iobase && !port->mapbase) + return; + + /* + * Now do the auto configuration stuff. Note that config_port + * is expected to claim the resources and map the port for us. + */ + flags = UART_CONFIG_TYPE; + if (port->flags & UPF_AUTO_IRQ) + flags |= UART_CONFIG_IRQ; + if (port->flags & UPF_BOOT_AUTOCONF) + port->ops->config_port(port, flags); + + /* + * Register the port whether it's detected or not. This allows + * setserial to be used to alter this ports parameters. + */ + tty_register_devfs(drv->tty_driver, 0, drv->minor + port->line); + + if (port->type != PORT_UNKNOWN) { + unsigned long flags; + + uart_report_port(drv, port); + + /* + * Ensure that the modem control lines are de-activated. + * We probably don't need a spinlock around this, but + */ + spin_lock_irqsave(&port->lock, flags); + port->ops->set_mctrl(port, 0); + spin_unlock_irqrestore(&port->lock, flags); + +#ifdef CONFIG_PM + /* + * Power down all ports by default, except the + * console if we have one. We need to drop the + * port semaphore here. + */ + if (state->pm && (!drv->cons || port->line != drv->cons->index)) { + up(&port_sem); + pm_send(state->pm, PM_SUSPEND, (void *)3); + down(&port_sem); + } +#endif + } +} + +/* + * Hangup the port. This must be done outside the port_sem + * since uart_hangup() grabs this same semaphore. Grr. + */ +static void +__uart_hangup_port(struct uart_driver *drv, struct uart_state *state) +{ + struct uart_info *info = state->info; + + if (info && info->tty) + tty_vhangup(info->tty); +} + +/* + * This reverses the affects of __uart_register_port. + */ +static void +__uart_unregister_port(struct uart_driver *drv, struct uart_state *state) +{ + struct uart_port *port = state->port; + struct uart_info *info = state->info; + + state->info = NULL; + + /* + * Remove the devices from devfs + */ + tty_unregister_devfs(drv->tty_driver, drv->minor + port->line); + + /* + * Free the port IO and memory resources, if any. + */ + if (port->type != PORT_UNKNOWN) + port->ops->release_port(port); + + /* + * Indicate that there isn't a port here anymore. + */ + port->type = PORT_UNKNOWN; + + /* + * Kill the tasklet, and free resources. + */ + if (info) { + tasklet_kill(&info->tlet); + kfree(info); + } +} + +/** + * uart_register_driver - register a driver with the uart core layer + * @drv: low level driver structure + * + * Register a uart driver with the core driver. We in turn register + * with the tty layer, and initialise the core driver per-port state. + * + * We have a proc file in /proc/tty/driver which is named after the + * normal driver. + * + * drv->port should be NULL, and the per-port structures should be + * registered using uart_add_one_port after this call has succeeded. + */ +int uart_register_driver(struct uart_driver *drv) +{ + struct tty_driver *normal = NULL; + struct termios **termios = NULL; + int i, retval; + + BUG_ON(drv->state); + + /* + * Maybe we should be using a slab cache for this, especially if + * we have a large number of ports to handle. Note that we also + * allocate space for an integer for reference counting. + */ + drv->state = kmalloc(sizeof(struct uart_state) * drv->nr + + sizeof(int), GFP_KERNEL); + retval = -ENOMEM; + if (!drv->state) + goto out; + + memset(drv->state, 0, sizeof(struct uart_state) * drv->nr + + sizeof(int)); + + termios = kmalloc(sizeof(struct termios *) * drv->nr * 2 + + sizeof(struct tty_struct *) * drv->nr, GFP_KERNEL); + if (!termios) + goto out; + + memset(termios, 0, sizeof(struct termios *) * drv->nr * 2 + + sizeof(struct tty_struct *) * drv->nr); + + normal = kmalloc(sizeof(struct tty_driver), GFP_KERNEL); + if (!normal) + goto out; + + memset(normal, 0, sizeof(struct tty_driver)); + + drv->tty_driver = normal; + + normal->magic = TTY_DRIVER_MAGIC; + normal->driver_name = drv->driver_name; + normal->name = drv->dev_name; + normal->major = drv->major; + normal->minor_start = drv->minor; + normal->num = drv->nr; + normal->type = TTY_DRIVER_TYPE_SERIAL; + normal->subtype = SERIAL_TYPE_NORMAL; + normal->init_termios = tty_std_termios; + normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + normal->refcount = (int *)(drv->state + drv->nr); + normal->termios = termios; + normal->termios_locked = termios + drv->nr; + normal->table = (struct tty_struct **)(termios + drv->nr * 2); + normal->driver_state = drv; + + normal->open = uart_open; + normal->close = uart_close; + normal->write = uart_write; + normal->put_char = uart_put_char; + normal->flush_chars = uart_flush_chars; + normal->write_room = uart_write_room; + normal->chars_in_buffer = uart_chars_in_buffer; + normal->flush_buffer = uart_flush_buffer; + normal->ioctl = uart_ioctl; + normal->throttle = uart_throttle; + normal->unthrottle = uart_unthrottle; + normal->send_xchar = uart_send_xchar; + normal->set_termios = uart_set_termios; + normal->stop = uart_stop; + normal->start = uart_start; + normal->hangup = uart_hangup; + normal->break_ctl = uart_break_ctl; + normal->wait_until_sent = uart_wait_until_sent; +#ifdef CONFIG_PROC_FS + normal->read_proc = uart_read_proc; +#endif + + /* + * Initialise the UART state(s). + */ + for (i = 0; i < drv->nr; i++) { + struct uart_state *state = drv->state + i; + + state->close_delay = 5 * HZ / 10; + state->closing_wait = 30 * HZ; +#ifdef CONFIG_PM + state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm); + if (state->pm) + state->pm->data = state; +#endif + } + + retval = tty_register_driver(normal); + out: + if (retval < 0) { +#ifdef CONFIG_PM + for (i = 0; i < drv->nr; i++) + pm_unregister(drv->state[i].pm); +#endif + kfree(normal); + kfree(drv->state); + kfree(termios); + } + return retval; +} + +/** + * uart_unregister_driver - remove a driver from the uart core layer + * @drv: low level driver structure + * + * Remove all references to a driver from the core driver. The low + * level driver must have removed all its ports via the + * uart_remove_one_port() if it registered them with uart_add_one_port(). + * (ie, drv->port == NULL) + */ +void uart_unregister_driver(struct uart_driver *drv) +{ + int i; + + for (i = 0; i < drv->nr; i++) + pm_unregister(drv->state[i].pm); + + tty_unregister_driver(drv->tty_driver); + + kfree(drv->state); + kfree(drv->tty_driver->termios); + kfree(drv->tty_driver); +} + +/** + * uart_add_one_port - attach a driver-defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure to use for this port. + * + * This allows the driver to register its own uart_port structure + * with the core driver. The main purpose is to allow the low + * level uart drivers to expand uart_port, rather than having yet + * more levels of structures. + */ +int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state; + + BUG_ON(in_interrupt()); + + if (port->line >= drv->nr) + return -EINVAL; + + state = drv->state + port->line; + + down(&port_sem); + __uart_register_port(drv, state, port); + up(&port_sem); + + return 0; +} + +/** + * uart_remove_one_port - detach a driver defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure for this port + * + * This unhooks (and hangs up) the specified port structure from the + * core driver. No further calls will be made to the low-level code + * for this port. + */ +int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state = drv->state + port->line; + + BUG_ON(in_interrupt()); + + if (state->port != port) + printk(KERN_ALERT "Removing wrong port: %p != %p\n", + state->port, port); + + __uart_hangup_port(drv, state); + + down(&port_sem); + __uart_unregister_port(drv, state); + state->port = NULL; + up(&port_sem); + + return 0; +} + +/* + * Are the two ports equivalent? + */ +static int uart_match_port(struct uart_port *port1, struct uart_port *port2) +{ + if (port1->iotype != port2->iotype) + return 0; + + switch (port1->iotype) { + case UPIO_PORT: + return (port1->iobase == port2->iobase); + case UPIO_HUB6: + return (port1->iobase == port2->iobase) && + (port1->hub6 == port2->hub6); + case UPIO_MEM: + return (port1->membase == port2->membase); + } + return 0; +} + +/* + * Try to find an unused uart_state slot for a port. + */ +static struct uart_state * +uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port) +{ + int i; + + /* + * First, find a port entry which matches. Note: if we do + * find a matching entry, and it has a non-zero use count, + * then we can't register the port. + */ + for (i = 0; i < drv->nr; i++) + if (uart_match_port(drv->state[i].port, port)) + return &drv->state[i]; + + /* + * We didn't find a matching entry, so look for the first + * free entry. We look for one which hasn't been previously + * used (indicated by zero iobase). + */ + for (i = 0; i < drv->nr; i++) + if (drv->state[i].port->type == PORT_UNKNOWN && + drv->state[i].port->iobase == 0 && + drv->state[i].count == 0) + return &drv->state[i]; + + /* + * That also failed. Last resort is to find any currently + * entry which doesn't have a real port associated with it. + */ + for (i = 0; i < drv->nr; i++) + if (drv->state[i].port->type == PORT_UNKNOWN && + drv->state[i].count == 0) + return &drv->state[i]; + + return NULL; +} + +/** + * uart_register_port: register uart settings with a port + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure describing the port + * + * Register UART settings with the specified low level driver. Detect + * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the + * IRQ if UPF_AUTO_IRQ is set. + * + * We try to pick the same port for the same IO base address, so that + * when a modem is plugged in, unplugged and plugged back in, it gets + * allocated the same port. + * + * Returns negative error, or positive line number. + */ +int uart_register_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state; + int ret; + + down(&port_sem); + + state = uart_find_match_or_unused(drv, port); + + if (state) { + /* + * Ok, we've found a line that we can use. + * + * If we find a port that matches this one, and it appears + * to be in-use (even if it doesn't have a type) we shouldn't + * alter it underneath itself - the port may be open and + * trying to do useful work. + */ + if (state->count != 0 || + (state->info && state->info->blocked_open != 0)) { + ret = -EBUSY; + goto out; + } + + state->port->iobase = port->iobase; + state->port->membase = port->membase; + state->port->irq = port->irq; + state->port->uartclk = port->uartclk; + state->port->fifosize = port->fifosize; + state->port->regshift = port->regshift; + state->port->iotype = port->iotype; + state->port->flags = port->flags; + state->port->line = drv->state - state; + + __uart_register_port(drv, state, state->port); + + ret = state->port->line; + } else + ret = -ENOSPC; + out: + up(&port_sem); + return ret; +} + +/** + * uart_unregister_port - de-allocate a port + * @drv: pointer to the uart low level driver structure for this port + * @line: line index previously returned from uart_register_port() + * + * Hang up the specified line associated with the low level driver, + * and mark the port as unused. + */ +void uart_unregister_port(struct uart_driver *drv, int line) +{ + struct uart_state *state; + + if (line < 0 || line >= drv->nr) { + printk(KERN_ERR "Attempt to unregister %s%d\n", + drv->dev_name, line); + return; + } + + state = drv->state + line; + + __uart_hangup_port(drv, state); + + down(&port_sem); + __uart_unregister_port(drv, state); + up(&port_sem); +} + +EXPORT_SYMBOL(uart_event); +EXPORT_SYMBOL(uart_register_driver); +EXPORT_SYMBOL(uart_unregister_driver); +EXPORT_SYMBOL(uart_register_port); +EXPORT_SYMBOL(uart_unregister_port); + +MODULE_DESCRIPTION("Serial driver core"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/sa1100.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,890 @@ +/* + * linux/drivers/char/sa1100.c + * + * Driver for SA11x0 serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2000 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 + * 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 + * + * $Id: sa1100.c,v 1.43 2002/07/22 15:27:32 rmk Exp $ + * + */ +#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 + +#if defined(CONFIG_SERIAL_SA1100_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +/* We've been assigned a range on the "Low-density serial ports" major */ +#define SERIAL_SA1100_MAJOR 204 +#define MINOR_START 5 + +#define NR_PORTS 3 + +#define SA1100_ISR_PASS_LIMIT 256 + +/* + * Convert from ignore_status_mask or read_status_mask to UTSR[01] + */ +#define SM_TO_UTSR0(x) ((x) & 0xff) +#define SM_TO_UTSR1(x) ((x) >> 8) +#define UTSR0_TO_SM(x) ((x)) +#define UTSR1_TO_SM(x) ((x) << 8) + +#define UART_GET_UTCR0(sport) __raw_readl((sport)->port.membase + UTCR0) +#define UART_GET_UTCR1(sport) __raw_readl((sport)->port.membase + UTCR1) +#define UART_GET_UTCR2(sport) __raw_readl((sport)->port.membase + UTCR2) +#define UART_GET_UTCR3(sport) __raw_readl((sport)->port.membase + UTCR3) +#define UART_GET_UTSR0(sport) __raw_readl((sport)->port.membase + UTSR0) +#define UART_GET_UTSR1(sport) __raw_readl((sport)->port.membase + UTSR1) +#define UART_GET_CHAR(sport) __raw_readl((sport)->port.membase + UTDR) + +#define UART_PUT_UTCR0(sport,v) __raw_writel((v),(sport)->port.membase + UTCR0) +#define UART_PUT_UTCR1(sport,v) __raw_writel((v),(sport)->port.membase + UTCR1) +#define UART_PUT_UTCR2(sport,v) __raw_writel((v),(sport)->port.membase + UTCR2) +#define UART_PUT_UTCR3(sport,v) __raw_writel((v),(sport)->port.membase + UTCR3) +#define UART_PUT_UTSR0(sport,v) __raw_writel((v),(sport)->port.membase + UTSR0) +#define UART_PUT_UTSR1(sport,v) __raw_writel((v),(sport)->port.membase + UTSR1) +#define UART_PUT_CHAR(sport,v) __raw_writel((v),(sport)->port.membase + UTDR) + +/* + * This is the size of our serial port register set. + */ +#define UART_PORT_SIZE 0x24 + +/* + * This determines how often we check the modem status signals + * for any change. They generally aren't connected to an IRQ + * so we have to poll them. We also check immediately before + * filling the TX fifo incase CTS has been dropped. + */ +#define MCTRL_TIMEOUT (250*HZ/1000) + +struct sa1100_port { + struct uart_port port; + struct timer_list timer; + unsigned int old_status; +}; + +/* + * Handle any change of modem status signal since we were last called. + */ +static void sa1100_mctrl_check(struct sa1100_port *sport) +{ + unsigned int status, changed; + + status = sport->port.ops->get_mctrl(&sport->port); + changed = status ^ sport->old_status; + + if (changed == 0) + return; + + sport->old_status = status; + + if (changed & TIOCM_RI) + sport->port.icount.rng++; + if (changed & TIOCM_DSR) + sport->port.icount.dsr++; + if (changed & TIOCM_CAR) + uart_handle_dcd_change(&sport->port, status & TIOCM_CAR); + if (changed & TIOCM_CTS) + uart_handle_cts_change(&sport->port, status & TIOCM_CTS); + + wake_up_interruptible(&sport->port.info->delta_msr_wait); +} + +/* + * This is our per-port timeout handler, for checking the + * modem status signals. + */ +static void sa1100_timeout(unsigned long data) +{ + struct sa1100_port *sport = (struct sa1100_port *)data; + unsigned long flags; + + if (sport->port.info) { + spin_lock_irqsave(&sport->port.lock, flags); + sa1100_mctrl_check(sport); + spin_unlock_irqrestore(&sport->port.lock, flags); + + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); + } +} + +/* + * interrupts disabled on entry + */ +static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + u32 utcr3; + + utcr3 = UART_GET_UTCR3(sport); + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_TIE); + sport->port.read_status_mask &= ~UTSR0_TO_SM(UTSR0_TFS); +} + +/* + * interrupts may not be disabled on entry + */ +static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + unsigned long flags; + u32 utcr3; + + spin_lock_irqsave(&sport->port.lock, flags); + utcr3 = UART_GET_UTCR3(sport); + sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); + UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + +/* + * Interrupts enabled + */ +static void sa1100_stop_rx(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + unsigned long flags; + u32 utcr3; + + spin_lock_irqsave(&sport->port.lock, flags); + utcr3 = UART_GET_UTCR3(sport); + UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + +/* + * Set the modem control timer to fire immediately. + */ +static void sa1100_enable_ms(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + mod_timer(&sport->timer, jiffies); +} + +static void +sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs) +{ + struct tty_struct *tty = sport->port.info->tty; + unsigned int status, ch, flg, ignored = 0; + + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | + UTSR0_TO_SM(UART_GET_UTSR0(sport)); + while (status & UTSR1_TO_SM(UTSR1_RNE)) { + ch = UART_GET_CHAR(sport); + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + sport->port.icount.rx++; + + flg = TTY_NORMAL; + + /* + * note that the error handling code is + * out of the main execution path + */ + if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) + goto handle_error; + + if (uart_handle_sysrq_char(&sport->port, ch, regs)) + goto ignore_char; + + error_return: + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + ignore_char: + status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) | + UTSR0_TO_SM(UART_GET_UTSR0(sport)); + } + out: + tty_flip_buffer_push(tty); + return; + + handle_error: + if (status & UTSR1_TO_SM(UTSR1_PRE)) + sport->port.icount.parity++; + else if (status & UTSR1_TO_SM(UTSR1_FRE)) + sport->port.icount.frame++; + if (status & UTSR1_TO_SM(UTSR1_ROR)) + sport->port.icount.overrun++; + + if (status & sport->port.ignore_status_mask) { + if (++ignored > 100) + goto out; + goto ignore_char; + } + + status &= sport->port.read_status_mask; + + if (status & UTSR1_TO_SM(UTSR1_PRE)) + flg = TTY_PARITY; + else if (status & UTSR1_TO_SM(UTSR1_FRE)) + flg = TTY_FRAME; + + if (status & UTSR1_TO_SM(UTSR1_ROR)) { + /* + * overrun does *not* affect the character + * we read from the FIFO + */ + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + ch = 0; + flg = TTY_OVERRUN; + } +#ifdef SUPPORT_SYSRQ + sport->port.sysrq = 0; +#endif + goto error_return; +} + +static void sa1100_tx_chars(struct sa1100_port *sport) +{ + struct circ_buf *xmit = &sport->port.info->xmit; + + if (sport->port.x_char) { + UART_PUT_CHAR(sport, sport->port.x_char); + sport->port.icount.tx++; + sport->port.x_char = 0; + return; + } + + /* + * Check the modem control lines before + * transmitting anything. + */ + sa1100_mctrl_check(sport); + + if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { + sa1100_stop_tx(&sport->port, 0); + return; + } + + /* + * Tried using FIFO (not checking TNF) for fifo fill: + * still had the '4 bytes repeated' problem. + */ + while (UART_GET_UTSR1(sport) & UTSR1_TNF) { + UART_PUT_CHAR(sport, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + sport->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(&sport->port, EVT_WRITE_WAKEUP); + + if (uart_circ_empty(xmit)) + sa1100_stop_tx(&sport->port, 0); +} + +static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct sa1100_port *sport = dev_id; + unsigned int status, pass_counter = 0; + + spin_lock(&sport->port.lock); + status = UART_GET_UTSR0(sport); + status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS; + do { + if (status & (UTSR0_RFS | UTSR0_RID)) { + /* Clear the receiver idle bit, if set */ + if (status & UTSR0_RID) + UART_PUT_UTSR0(sport, UTSR0_RID); + sa1100_rx_chars(sport, regs); + } + + /* Clear the relevent break bits */ + if (status & (UTSR0_RBB | UTSR0_REB)) + UART_PUT_UTSR0(sport, status & (UTSR0_RBB | UTSR0_REB)); + + if (status & UTSR0_RBB) + sport->port.icount.brk++; + + if (status & UTSR0_REB) + uart_handle_break(&sport->port); + + if (status & UTSR0_TFS) + sa1100_tx_chars(sport); + if (pass_counter++ > SA1100_ISR_PASS_LIMIT) + break; + status = UART_GET_UTSR0(sport); + status &= SM_TO_UTSR0(sport->port.read_status_mask) | + ~UTSR0_TFS; + } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); + spin_unlock(&sport->port.lock); +} + +/* + * Return TIOCSER_TEMT when transmitter is not busy. + */ +static unsigned int sa1100_tx_empty(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + return UART_GET_UTSR1(sport) & UTSR1_TBY ? 0 : TIOCSER_TEMT; +} + +static unsigned int sa1100_get_mctrl(struct uart_port *port) +{ + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; +} + +static void sa1100_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +/* + * Interrupts always disabled. + */ +static void sa1100_break_ctl(struct uart_port *port, int break_state) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + unsigned long flags; + unsigned int utcr3; + + spin_lock_irqsave(&sport->port.lock, flags); + utcr3 = UART_GET_UTCR3(sport); + if (break_state == -1) + utcr3 |= UTCR3_BRK; + else + utcr3 &= ~UTCR3_BRK; + UART_PUT_UTCR3(sport, utcr3); + spin_unlock_irqrestore(&sport->port.lock, flags); +} + +static int sa1100_startup(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + int retval; + + /* + * Allocate the IRQ + */ + retval = request_irq(sport->port.irq, sa1100_int, 0, + "serial_sa1100", sport); + if (retval) + return retval; + + /* + * Finally, clear and enable interrupts + */ + UART_PUT_UTSR0(sport, -1); + UART_PUT_UTCR3(sport, UTCR3_RXE | UTCR3_TXE | UTCR3_RIE); + + /* + * Enable modem status interrupts + */ + sa1100_enable_ms(&sport->port); + + return 0; +} + +static void sa1100_shutdown(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + /* + * Stop our timer. + */ + del_timer_sync(&sport->timer); + + /* + * Free the interrupt + */ + free_irq(sport->port.irq, sport); + + /* + * Disable all interrupts, port and break condition. + */ + UART_PUT_UTCR3(sport, 0); +} + +static void +sa1100_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + unsigned long flags; + unsigned int utcr0, old_utcr3; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS7: + utcr0 = 0; + break; + default: + utcr0 = UTCR0_DSS; + break; + } + if (cflag & CSTOPB) + utcr0 |= UTCR0_SBS; + if (cflag & PARENB) { + utcr0 |= UTCR0_PE; + if (!(cflag & PARODD)) + utcr0 |= UTCR0_OES; + } + + sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); + sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); + if (iflag & INPCK) + sport->port.read_status_mask |= + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); + if (iflag & (BRKINT | PARMRK)) + sport->port.read_status_mask |= + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); + + /* + * Characters to ignore + */ + sport->port.ignore_status_mask = 0; + if (iflag & IGNPAR) + sport->port.ignore_status_mask |= + UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); + if (iflag & IGNBRK) { + sport->port.ignore_status_mask |= + UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (iflag & IGNPAR) + sport->port.ignore_status_mask |= + UTSR1_TO_SM(UTSR1_ROR); + } + + del_timer_sync(&sport->timer); + + /* first, disable interrupts and drain transmitter */ + spin_lock_irqsave(&sport->port.lock, flags); + old_utcr3 = UART_GET_UTCR3(sport); + UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); + + while (UART_GET_UTSR1(sport) & UTSR1_TBY); + + /* then, disable everything */ + UART_PUT_UTCR3(sport, 0); + + /* set the parity, stop bits and data size */ + UART_PUT_UTCR0(sport, utcr0); + + /* set the baud rate */ + quot -= 1; + UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8)); + UART_PUT_UTCR2(sport, (quot & 0xff)); + + UART_PUT_UTSR0(sport, -1); + + UART_PUT_UTCR3(sport, old_utcr3); + spin_unlock_irqrestore(&sport->port.lock, flags); + + if (UART_ENABLE_MS(&sport->port, cflag)) + sa1100_enable_ms(&sport->port); +} + +static const char *sa1100_type(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + return sport->port.type == PORT_SA1100 ? "SA1100" : NULL; +} + +/* + * Release the memory region(s) being used by 'port'. + */ +static void sa1100_release_port(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + release_mem_region(sport->port.mapbase, UART_PORT_SIZE); +} + +/* + * Request the memory region(s) being used by 'port'. + */ +static int sa1100_request_port(struct uart_port *port) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + return request_mem_region(sport->port.mapbase, UART_PORT_SIZE, + "serial_sa1100") != NULL ? 0 : -EBUSY; +} + +/* + * Configure/autoconfigure the port. + */ +static void sa1100_config_port(struct uart_port *port, int flags) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + + if (flags & UART_CONFIG_TYPE && + sa1100_request_port(&sport->port) == 0) + sport->port.type = PORT_SA1100; +} + +/* + * Verify the new serial_struct (for TIOCSSERIAL). + * The only change we allow are to the flags and type, and + * even then only between PORT_SA1100 and PORT_UNKNOWN + */ +static int +sa1100_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + struct sa1100_port *sport = (struct sa1100_port *)port; + int ret = 0; + + if (ser->type != PORT_UNKNOWN && ser->type != PORT_SA1100) + ret = -EINVAL; + if (sport->port.irq != ser->irq) + ret = -EINVAL; + if (ser->io_type != SERIAL_IO_MEM) + ret = -EINVAL; + if (sport->port.uartclk / 16 != ser->baud_base) + ret = -EINVAL; + if ((void *)sport->port.mapbase != ser->iomem_base) + ret = -EINVAL; + if (sport->port.iobase != ser->port) + ret = -EINVAL; + if (ser->hub6 != 0) + ret = -EINVAL; + return ret; +} + +static struct uart_ops sa1100_pops = { + tx_empty: sa1100_tx_empty, + set_mctrl: sa1100_set_mctrl, + get_mctrl: sa1100_get_mctrl, + stop_tx: sa1100_stop_tx, + start_tx: sa1100_start_tx, + stop_rx: sa1100_stop_rx, + enable_ms: sa1100_enable_ms, + break_ctl: sa1100_break_ctl, + startup: sa1100_startup, + shutdown: sa1100_shutdown, + change_speed: sa1100_change_speed, + type: sa1100_type, + release_port: sa1100_release_port, + request_port: sa1100_request_port, + config_port: sa1100_config_port, + verify_port: sa1100_verify_port, +}; + +static struct sa1100_port sa1100_ports[NR_PORTS]; + +/* + * Setup the SA1100 serial ports. Note that we don't include the IrDA + * port here since we have our own SIR/FIR driver (see drivers/net/irda) + * + * Note also that we support "console=ttySAx" where "x" is either 0 or 1. + * Which serial port this ends up being depends on the machine you're + * running this kernel on. I'm not convinced that this is a good idea, + * but that's the way it traditionally works. + * + * Note that NanoEngine UART3 becomes UART2, and UART2 is no longer + * used here. + */ +static void __init sa1100_init_ports(void) +{ + static int first = 1; + int i; + + if (!first) + return; + first = 0; + + for (i = 0; i < NR_PORTS; i++) { + sa1100_ports[i].port.uartclk = 3686400; + sa1100_ports[i].port.ops = &sa1100_pops; + sa1100_ports[i].port.fifosize = 8; + sa1100_ports[i].port.line = i; + sa1100_ports[i].port.iotype = SERIAL_IO_MEM; + init_timer(&sa1100_ports[i].timer); + sa1100_ports[i].timer.function = sa1100_timeout; + sa1100_ports[i].timer.data = (unsigned long)&sa1100_ports[i]; + } + + /* + * make transmit lines outputs, so that when the port + * is closed, the output is in the MARK state. + */ + PPDR |= PPC_TXD1 | PPC_TXD3; + PPSR |= PPC_TXD1 | PPC_TXD3; +} + +void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns) +{ + if (fns->get_mctrl) + sa1100_pops.get_mctrl = fns->get_mctrl; + if (fns->set_mctrl) + sa1100_pops.set_mctrl = fns->set_mctrl; + + sa1100_pops.pm = fns->pm; + sa1100_pops.set_wake = fns->set_wake; +} + +void __init sa1100_register_uart(int idx, int port) +{ + if (idx >= NR_PORTS) { + printk(KERN_ERR __FUNCTION__ ": bad index number %d\n", idx); + return; + } + + switch (port) { + case 1: + sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0; + sa1100_ports[idx].port.mapbase = _Ser1UTCR0; + sa1100_ports[idx].port.irq = IRQ_Ser1UART; + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + break; + + case 2: + sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0; + sa1100_ports[idx].port.mapbase = _Ser2UTCR0; + sa1100_ports[idx].port.irq = IRQ_Ser2ICP; + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + break; + + case 3: + sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0; + sa1100_ports[idx].port.mapbase = _Ser3UTCR0; + sa1100_ports[idx].port.irq = IRQ_Ser3UART; + sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF; + break; + + default: + printk(KERN_ERR __FUNCTION__ ": bad port number %d\n", port); + } +} + + +#ifdef CONFIG_SERIAL_SA1100_CONSOLE + +/* + * Interrupts are disabled on entering + */ +static void +sa1100_console_write(struct console *co, const char *s, unsigned int count) +{ + struct sa1100_port *sport = &sa1100_ports[co->index]; + unsigned int old_utcr3, status, i; + + /* + * First, save UTCR3 and then disable interrupts + */ + old_utcr3 = UART_GET_UTCR3(sport); + UART_PUT_UTCR3(sport, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | + UTCR3_TXE); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + do { + status = UART_GET_UTSR1(sport); + } while (!(status & UTSR1_TNF)); + UART_PUT_CHAR(sport, s[i]); + if (s[i] == '\n') { + do { + status = UART_GET_UTSR1(sport); + } while (!(status & UTSR1_TNF)); + UART_PUT_CHAR(sport, '\r'); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore UTCR3 + */ + do { + status = UART_GET_UTSR1(sport); + } while (status & UTSR1_TBY); + UART_PUT_UTCR3(sport, old_utcr3); +} + +static kdev_t sa1100_console_device(struct console *co) +{ + return mk_kdev(SERIAL_SA1100_MAJOR, MINOR_START + co->index); +} + +/* + * If the port was already initialised (eg, by a boot loader), + * try to determine the current setup. + */ +static void __init +sa1100_console_get_options(struct sa1100_port *sport, int *baud, + int *parity, int *bits) +{ + unsigned int utcr3; + + utcr3 = UART_GET_UTCR3(sport) & (UTCR3_RXE | UTCR3_TXE); + if (utcr3 == (UTCR3_RXE | UTCR3_TXE)) { + /* ok, the port was enabled */ + unsigned int utcr0, quot; + + utcr0 = UART_GET_UTCR0(sport); + + *parity = 'n'; + if (utcr0 & UTCR0_PE) { + if (utcr0 & UTCR0_OES) + *parity = 'e'; + else + *parity = 'o'; + } + + if (utcr0 & UTCR0_DSS) + *bits = 8; + else + *bits = 7; + + quot = UART_GET_UTCR2(sport) | UART_GET_UTCR1(sport) << 8; + quot &= 0xfff; + *baud = sport->port.uartclk / (16 * (quot + 1)); + } +} + +static int __init +sa1100_console_setup(struct console *co, char *options) +{ + struct sa1100_port *sport; + 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 == -1 || co->index >= NR_PORTS) + co->index = 0; + sport = &sa1100_ports[co->index]; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + sa1100_console_get_options(sport, &baud, &parity, &bits); + + return uart_set_options(&sport->port, co, baud, parity, bits, flow); +} + +static struct console sa1100_console = { + name: "ttySA", + write: sa1100_console_write, + device: sa1100_console_device, + setup: sa1100_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init sa1100_rs_console_init(void) +{ + sa1100_init_ports(); + register_console(&sa1100_console); +} + +#define SA1100_CONSOLE &sa1100_console +#else +#define SA1100_CONSOLE NULL +#endif + +static struct uart_driver sa1100_reg = { + owner: THIS_MODULE, + driver_name: "ttySA", +#ifdef CONFIG_DEVFS_FS + dev_name: "ttySA%d", +#else + dev_name: "ttySA", +#endif + major: SERIAL_SA1100_MAJOR, + minor: MINOR_START, + nr: NR_PORTS, + cons: SA1100_CONSOLE, +}; + +static int __init sa1100_serial_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.43 $\n"); + + sa1100_init_ports(); + ret = uart_register_driver(&sa1100_reg); + if (ret == 0) { + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_add_one_port(&sa1100_reg, &sa1100_ports[i].port); + } + return ret; +} + +static void __exit sa1100_serial_exit(void) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_remove_one_port(&sa1100_reg, &sa1100_ports[i].port); + + uart_unregister_driver(&sa1100_reg); +} + +module_init(sa1100_serial_init); +module_exit(sa1100_serial_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR("Deep Blue Solutions Ltd"); +MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.43 $"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/uart00.c Wed Jul 24 14:03:39 2002 @@ -0,0 +1,778 @@ +/* + * linux/drivers/char/uart00.c + * + * Driver for UART00 serial ports + * + * Based on drivers/char/serial_amba.c, by ARM Limited & + * Deep Blue Solutions Ltd. + * Copyright 2001 Altera 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 + * + * $Id: uart00.c,v 1.33 2002/07/21 21:32:31 rmk Exp $ + * + */ +#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 + +#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#define UART00_TYPE (volatile unsigned int*) +#include +#include + +#define UART_NR 2 + +#define SERIAL_UART00_NAME "ttyUA" +#define SERIAL_UART00_MAJOR 204 +#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */ +#define SERIAL_UART00_NR UART_NR +#define UART_PORT_SIZE 0x50 + +#define UART00_ISR_PASS_LIMIT 256 + +/* + * Access macros for the UART00 UARTs + */ +#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase)) +#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase)) +#define UART_GET_IES(p) inl(UART_IES((p)->membase)) +#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase)) +#define UART_GET_IEC(p) inl(UART_IEC((p)->membase)) +#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase)) +#define UART_GET_CHAR(p) inl(UART_RD((p)->membase)) +#define UART_GET_RSR(p) inl(UART_RSR((p)->membase)) +#define UART_GET_RDS(p) inl(UART_RDS((p)->membase)) +#define UART_GET_MSR(p) inl(UART_MSR((p)->membase)) +#define UART_GET_MCR(p) inl(UART_MCR((p)->membase)) +#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase)) +#define UART_GET_MC(p) inl(UART_MC((p)->membase)) +#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase)) +#define UART_GET_TSR(p) inl(UART_TSR((p)->membase)) +#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase)) +#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase)) +#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase)) +#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase)) +#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK) +#define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15) +//#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0) + +static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + UART_PUT_IEC(port, UART_IEC_TIE_MSK); +} + +static void uart00_stop_rx(struct uart_port *port) +{ + UART_PUT_IEC(port, UART_IEC_RE_MSK); +} + +static void uart00_enable_ms(struct uart_port *port) +{ + UART_PUT_IES(port, UART_IES_ME_MSK); +} + +static void +uart00_rx_chars(struct uart_port *port, struct pt_regs *regs) +{ + struct tty_struct *tty = port->info->tty; + unsigned int status, ch, rds, flg, ignored = 0; + + status = UART_GET_RSR(port); + while (UART_RX_DATA(status)) { + /* + * We need to read rds before reading the + * character from the fifo + */ + rds = UART_GET_RDS(port); + ch = UART_GET_CHAR(port); + port->icount.rx++; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + + flg = TTY_NORMAL; + + /* + * Note that the error handling code is + * out of the main execution path + */ + if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK| + UART_RDS_PE_MSK |UART_RDS_PE_MSK)) + goto handle_error; + if (uart_handle_sysrq_char(port, ch, regs)) + goto ignore_char; + + error_return: + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + ignore_char: + status = UART_GET_RSR(port); + } + out: + tty_flip_buffer_push(tty); + return; + + handle_error: + if (rds & UART_RDS_BI_MSK) { + status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK); + port->icount.brk++; + if (uart_handle_break(port)) + goto ignore_char; + } else if (rds & UART_RDS_PE_MSK) + port->icount.parity++; + else if (rds & UART_RDS_PE_MSK) + port->icount.frame++; + if (rds & UART_RDS_OE_MSK) + port->icount.overrun++; + + if (rds & port->ignore_status_mask) { + if (++ignored > 100) + goto out; + goto ignore_char; + } + rds &= port->read_status_mask; + + if (rds & UART_RDS_BI_MSK) + flg = TTY_BREAK; + else if (rds & UART_RDS_PE_MSK) + flg = TTY_PARITY; + else if (rds & UART_RDS_FE_MSK) + flg = TTY_FRAME; + + if (status & UART_RDS_OE_MSK) { + /* + * CHECK: does overrun affect the current character? + * ASSUMPTION: it does not. + */ + *tty->flip.flag_buf_ptr++ = flg; + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + goto ignore_char; + ch = 0; + flg = TTY_OVERRUN; + } +#ifdef SUPPORT_SYSRQ + port->sysrq = 0; +#endif + goto error_return; +} + +static void uart00_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + int count; + + if (port->x_char) { + while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15); + UART_PUT_CHAR(port, port->x_char); + port->icount.tx++; + port->x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + uart00_stop_tx(port, 0); + return; + } + + count = port->fifosize >> 1; + do { + while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15); + UART_PUT_CHAR(port, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_event(port, EVT_WRITE_WAKEUP); + + if (uart_circ_empty(xmit)) + uart00_stop_tx(port, 0); +} + +static void uart00_start_tx(struct uart_port *port, unsigned int tty_start) +{ + UART_PUT_IES(port, UART_IES_TIE_MSK); + uart00_tx_chars(port); +} + +static void uart00_modem_status(struct uart_port *port) +{ + unsigned int status; + + status = UART_GET_MSR(port); + + if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK | + UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)) + return; + + if (status & UART_MSR_DDCD_MSK) + uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK); + + if (status & UART_MSR_DDSR_MSK) + port->icount.dsr++; + + if (status & UART_MSR_DCTS_MSK) + uart_handle_cts_change(port, status & UART_MSR_CTS_MSK); + + wake_up_interruptible(&port->info->delta_msr_wait); +} + +static void uart00_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = dev_id; + unsigned int status, pass_counter = 0; + + status = UART_GET_INT_STATUS(port); + do { + if (status & UART_ISR_RI_MSK) + uart00_rx_chars(port, regs); + if (status & UART_ISR_MI_MSK) + uart00_modem_status(port); + if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK)) + uart00_tx_chars(port); + if (pass_counter++ > UART00_ISR_PASS_LIMIT) + break; + + status = UART_GET_INT_STATUS(port); + } while (status); +} + +static unsigned int uart00_tx_empty(struct uart_port *port) +{ + return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT; +} + +static unsigned int uart00_get_mctrl(struct uart_port *port) +{ + unsigned int result = 0; + unsigned int status; + + status = UART_GET_MSR(port); + if (status & UART_MSR_DCD_MSK) + result |= TIOCM_CAR; + if (status & UART_MSR_DSR_MSK) + result |= TIOCM_DSR; + if (status & UART_MSR_CTS_MSK) + result |= TIOCM_CTS; + if (status & UART_MSR_RI_MSK) + result |= TIOCM_RI; + + return result; +} + +static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl) +{ +} + +static void uart00_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + unsigned int mcr; + + spin_lock_irqsave(&port->lock, flags); + mcr = UART_GET_MCR(port); + if (break_state == -1) + mcr |= UART_MCR_BR_MSK; + else + mcr &= ~UART_MCR_BR_MSK; + UART_PUT_MCR(port, mcr); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void +uart00_change_speed(struct uart_port *port, unsigned int cflag, + unsigned int iflag, unsigned int quot) +{ + unsigned int uart_mc, old_ies; + unsigned long flags; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + uart_mc = UART_MC_CLS_CHARLEN_5; + break; + case CS6: + uart_mc = UART_MC_CLS_CHARLEN_6; + break; + case CS7: + uart_mc = UART_MC_CLS_CHARLEN_7; + break; + default: // CS8 + uart_mc = UART_MC_CLS_CHARLEN_8; + break; + } + if (cflag & CSTOPB) + uart_mc|= UART_MC_ST_TWO; + if (cflag & PARENB) { + uart_mc |= UART_MC_PE_MSK; + if (!(cflag & PARODD)) + uart_mc |= UART_MC_EP_MSK; + } + + port->read_status_mask = UART_RDS_OE_MSK; + if (iflag & INPCK) + port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; + if (iflag & (BRKINT | PARMRK)) + port->read_status_mask |= UART_RDS_BI_MSK; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (iflag & IGNPAR) + port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK; + if (iflag & IGNBRK) { + port->ignore_status_mask |= UART_RDS_BI_MSK; + /* + * If we're ignoring parity and break indicators, + * ignore overruns to (for real raw support). + */ + if (iflag & IGNPAR) + port->ignore_status_mask |= UART_RDS_OE_MSK; + } + + /* first, disable everything */ + spin_lock_irqsave(&port->lock, flags); + old_ies = UART_GET_IES(port); + + if (UART_ENABLE_MS(port, cflag)) + old_ies |= UART_IES_ME_MSK; + + /* Set baud rate */ + UART_PUT_DIV_LO(port, (quot & 0xff)); + UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8)); + + UART_PUT_MC(port, uart_mc); + UART_PUT_IES(port, old_ies); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static int uart00_startup(struct uart_port *port) +{ + int result; + + /* + * Allocate the IRQ + */ + result = request_irq(port->irq, uart00_int, 0, "uart00", port); + if (result) { + printk(KERN_ERR "Request of irq %d failed\n", port->irq); + return result; + } + + /* + * Finally, enable interrupts. Use the TII interrupt to minimise + * the number of interrupts generated. If higher performance is + * needed, consider using the TI interrupt with a suitable FIFO + * threshold + */ + UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK); + + return 0; +} + +static void uart00_shutdown(struct uart_port *port) +{ + /* + * disable all interrupts, disable the port + */ + UART_PUT_IEC(port, 0xff); + + /* disable break condition and fifos */ + UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK); + + /* + * Free the interrupt + */ + free_irq(port->irq, port); +} + +static const char *uart00_type(struct uart_port *port) +{ + return port->type == PORT_UART00 ? "Altera UART00" : NULL; +} + +/* + * Release the memory region(s) being used by 'port' + */ +static void uart00_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, UART_PORT_SIZE); + +#ifdef CONFIG_ARCH_CAMELOT + if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) { + iounmap(port->membase); + } +#endif +} + +/* + * Request the memory region(s) being used by 'port' + */ +static int uart00_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00") + != NULL ? 0 : -EBUSY; +} + +/* + * Configure/autoconfigure the port. + */ +static void uart00_config_port(struct uart_port *port, int flags) +{ + + /* + * Map the io memory if this is a soft uart + */ + if (!port->membase) + port->membase = ioremap_nocache(port->mapbase,SZ_4K); + + if (!port->membase) + printk(KERN_ERR "serial00: cannot map io memory\n"); + else + port->type = PORT_UART00; + +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00) + ret = -EINVAL; + if (ser->irq < 0 || ser->irq >= NR_IRQS) + ret = -EINVAL; + if (ser->baud_base < 9600) + ret = -EINVAL; + return ret; +} + +static struct uart_ops uart00_pops = { + tx_empty: uart00_tx_empty, + set_mctrl: uart00_set_mctrl_null, + get_mctrl: uart00_get_mctrl, + stop_tx: uart00_stop_tx, + start_tx: uart00_start_tx, + stop_rx: uart00_stop_rx, + enable_ms: uart00_enable_ms, + break_ctl: uart00_break_ctl, + startup: uart00_startup, + shutdown: uart00_shutdown, + change_speed: uart00_change_speed, + type: uart00_type, + release_port: uart00_release_port, + request_port: uart00_request_port, + config_port: uart00_config_port, + verify_port: uart00_verify_port, +}; + + +#ifdef CONFIG_ARCH_CAMELOT +static struct uart_port epxa10db_port = { + membase: (void*)IO_ADDRESS(EXC_UART00_BASE), + mapbase: EXC_UART00_BASE, + iotype: SERIAL_IO_MEM, + irq: IRQ_UART, + uartclk: EXC_AHB2_CLK_FREQUENCY, + fifosize: 16, + ops: &uart00_pops, + flags: ASYNC_BOOT_AUTOCONF, +}; +#endif + + +#ifdef CONFIG_SERIAL_UART00_CONSOLE +static void uart00_console_write(struct console *co, const char *s, unsigned count) +{ +#ifdef CONFIG_ARCH_CAMELOT + struct uart_port *port = &epxa10db_port; + unsigned int status, old_ies; + int i; + + /* + * First save the CR then disable the interrupts + */ + old_ies = UART_GET_IES(port); + UART_PUT_IEC(port,0xff); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + do { + status = UART_GET_TSR(port); + } while (!UART_TX_READY(status)); + UART_PUT_CHAR(port, s[i]); + if (s[i] == '\n') { + do { + status = UART_GET_TSR(port); + } while (!UART_TX_READY(status)); + UART_PUT_CHAR(port, '\r'); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IES + */ + do { + status = UART_GET_TSR(port); + } while (status & UART_TSR_TX_LEVEL_MSK); + UART_PUT_IES(port, old_ies); +#endif +} + +static kdev_t uart00_console_device(struct console *co) +{ + return mk_kdev(SERIAL_UART00_MAJOR, SERIAL_UART00_MINOR + co->index); +} + +static void __init +uart00_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits) +{ + unsigned int uart_mc, quot; + + uart_mc = UART_GET_MC(port); + + *parity = 'n'; + if (uart_mc & UART_MC_PE_MSK) { + if (uart_mc & UART_MC_EP_MSK) + *parity = 'e'; + else + *parity = 'o'; + } + + switch (uart_mc & UART_MC_CLS_MSK) { + case UART_MC_CLS_CHARLEN_5: + *bits = 5; + break; + case UART_MC_CLS_CHARLEN_6: + *bits = 6; + break; + case UART_MC_CLS_CHARLEN_7: + *bits = 7; + break; + case UART_MC_CLS_CHARLEN_8: + *bits = 8; + break; + } + quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8); + *baud = port->uartclk / (16 *quot ); +} + +static int __init uart00_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 38400; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + +#ifdef CONFIG_ARCH_CAMELOT + port = &epxa10db_port; ; +#else + return -ENODEV; +#endif + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + uart00_console_get_options(port, &baud, &parity, &bits); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct console uart00_console = { + name: SERIAL_UART00_NAME, + write: uart00_console_write, + device: uart00_console_device, + setup: uart00_console_setup, + flags: CON_PRINTBUFFER, + index: 0, +}; + +void __init uart00_console_init(void) +{ + register_console(&uart00_console); +} + +#define UART00_CONSOLE &uart00_console +#else +#define UART00_CONSOLE NULL +#endif + +static struct uart_driver uart00_reg = { + owner: NULL, + driver_name: SERIAL_UART00_NAME, + dev_name: SERIAL_UART00_NAME, + major: SERIAL_UART00_MAJOR, + minor: SERIAL_UART00_MINOR, + nr: UART_NR, + cons: UART00_CONSOLE, +}; + +struct dev_port_entry{ + unsigned int base_addr; + struct uart_port *port; +}; + +static struct dev_port_entry dev_port_map[UART_NR]; + +#ifdef CONFIG_PLD_HOTSWAP +/* + * Keep a mapping of dev_info addresses -> port lines to use when + * removing ports dev==NULL indicates unused entry + */ + +struct uart00_ps_data{ + unsigned int clk; + unsigned int fifosize; +}; + +int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data) +{ + struct uart00_ps_data* dev_ps=dev_ps_data; + struct uart_port * port; + int i,result; + + i=0; + while(dev_port_map[i].port) + i++; + + if(i==UART_NR){ + printk(KERN_WARNING "uart00: Maximum number of ports reached\n"); + return 0; + } + + port=kmalloc(sizeof(struct uart_port),GFP_KERNEL); + if(!port) + return -ENOMEM; + + printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize); + port->membase=0; + port->mapbase=dev_info->base_addr; + port->iotype=SERIAL_IO_MEM; + port->irq=dev_info->irq; + port->uartclk=dev_ps->clk; + port->fifosize=dev_ps->fifosize; + port->ops=&uart00_pops; + port->line=i; + port->flags=ASYNC_BOOT_AUTOCONF; + + result=uart_add_one_port(&uart00_reg, port); + if(result){ + printk("uart_add_one_port returned %d\n",result); + return result; + } + dev_port_map[i].base_addr=dev_info->base_addr; + dev_port_map[i].port=port; + printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i); + return 0; + +} + +int uart00_remove_devices(void) +{ + int i,result; + + + result=0; + for(i=1;iactconfig->bConfigurationValue); } static struct driver_file_entry usb_config_entry = { @@ -851,7 +851,7 @@ if (off) return 0; - interface = list_entry (dev, struct usb_interface, dev); + interface = to_usb_interface (dev); return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting); } static struct driver_file_entry usb_altsetting_entry = { @@ -868,7 +868,7 @@ if (off) return 0; - udev = list_entry (dev, struct usb_device, dev); + udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE); buf[len] = '\n'; @@ -890,7 +890,7 @@ if (off) return 0; - udev = list_entry (dev, struct usb_device, dev); + udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE); buf[len] = '\n'; @@ -912,7 +912,7 @@ if (off) return 0; - udev = list_entry (dev, struct usb_device, dev); + udev = to_usb_device (dev); len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE); buf[len] = '\n'; @@ -947,8 +947,9 @@ /* register this interface with driverfs */ interface->dev.parent = &dev->dev; interface->dev.bus = &usb_bus_type; - sprintf (&interface->dev.bus_id[0], "if%d", - interface->altsetting->bInterfaceNumber); + sprintf (&interface->dev.bus_id[0], "%s:%d", + dev->devpath, + interface->altsetting->bInterfaceNumber); if (!desc->iInterface || usb_string (dev, desc->iInterface, interface->dev.name, @@ -1288,56 +1289,59 @@ */ static void set_device_description (struct usb_device *dev) { - char *buf, *here, *end; + void *buf; int mfgr = dev->descriptor.iManufacturer; int prod = dev->descriptor.iProduct; + int vendor_id = dev->descriptor.idVendor; + int product_id = dev->descriptor.idProduct; + char *mfgr_str, *prod_str; - /* set default; keep it if there are no strings */ + /* set default; keep it if there are no strings, or kmalloc fails */ sprintf (dev->dev.name, "USB device %04x:%04x", - dev->descriptor.idVendor, - dev->descriptor.idProduct); - if (!mfgr && !prod) - return; + vendor_id, product_id); - if (!(buf = kmalloc(256, GFP_KERNEL))) + if (!(buf = kmalloc(256 * 2, GFP_KERNEL))) return; - here = dev->dev.name; - end = here + sizeof dev->dev.name - 2; - *end = 0; + + prod_str = (char *) buf; + mfgr_str = (char *) buf + 256; - /* much like pci ... describe as either: - * - both strings: 'product descr (vendor descr)' - * - product only: 'product descr (USB device vvvv:pppp)' - * - vendor only: 'USB device vvvv:pppp (vendor descr)' - * - neither string: 'USB device vvvv:pppp' - */ - if (prod && usb_string (dev, prod, buf, 256) > 0) { - strncpy (here, buf, end - here); + if (prod && usb_string (dev, prod, prod_str, 256) > 0) { #ifdef DEBUG - printk (KERN_INFO "Product: %s\n", buf); + printk (KERN_INFO "Product: %s\n", prod_str); #endif } else { - buf [0] = 0; - prod = -1; + prod_str = 0; } - here = strchr (here, 0); - if (mfgr && usb_string (dev, mfgr, buf, 256) > 0) { - *here++ = ' '; - *here++ = '('; - strncpy (here, buf, end - here - 1); - here = strchr (here, 0); - *here++ = ')'; + + if (mfgr && usb_string (dev, mfgr, mfgr_str, 256) > 0) { #ifdef DEBUG - printk (KERN_INFO "Manufacturer: %s\n", buf); + printk (KERN_INFO "Manufacturer: %s\n", mfgr_str); #endif } else { - if (prod != -1) - snprintf (here, end - here - 1, - " (USB device %04x:%04x)", - dev->descriptor.idVendor, - dev->descriptor.idProduct); - /* both strings unavailable, keep the default */ + mfgr_str = 0; + } + + /* much like pci ... describe as either: + * - both strings: 'product descr (vendor descr)' + * - product only: 'product descr (USB device vvvv:pppp)' + * - vendor only: 'USB device vvvv:pppp (vendor descr)' + * - neither string: 'USB device vvvv:pppp' + */ + + if (prod_str && mfgr_str) { + snprintf(dev->dev.name, sizeof dev->dev.name, + "%s (%s)", prod_str, mfgr_str); + } else if (prod_str) { + snprintf(dev->dev.name, sizeof dev->dev.name, + "%s (USB device %04x:%04x)", + prod_str, vendor_id, product_id); + } else if (mfgr_str) { + snprintf(dev->dev.name, sizeof dev->dev.name, + "USB device %04x:%04x (%s)", + vendor_id, product_id, mfgr_str); } + kfree(buf); } diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c --- a/drivers/usb/host/ohci-sa1111.c Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/host/ohci-sa1111.c Wed Jul 24 14:03:38 2002 @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c Wed Jul 24 14:03:39 2002 +++ b/drivers/usb/host/uhci-hcd.c Wed Jul 24 14:03:39 2002 @@ -2053,6 +2053,8 @@ /* Run and mark it configured with a 64-byte max packet */ outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); + + uhci->hcd.state = USB_STATE_READY; } #ifdef CONFIG_PROC_FS @@ -2343,8 +2345,6 @@ /* disable legacy emulation */ pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); - - hcd->state = USB_STATE_READY; usb_connect(uhci->rh_dev); uhci->rh_dev->speed = USB_SPEED_FULL; diff -Nru a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c --- a/drivers/usb/input/hid-ff.c Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/input/hid-ff.c Wed Jul 24 14:03:38 2002 @@ -83,7 +83,7 @@ hid->dev->descriptor.idProduct); if (!init) { - warn("hid_ff_init could not find initializer"); + dbg("hid_ff_init could not find initializer"); return -ENOSYS; } return init->init(hid); diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c --- a/drivers/usb/misc/rio500.c Wed Jul 24 14:03:35 2002 +++ b/drivers/usb/misc/rio500.c Wed Jul 24 14:03:35 2002 @@ -146,7 +146,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } @@ -216,7 +216,7 @@ retval = -EFAULT; goto err_out; } - if (rio_cmd.length > PAGE_SIZE) { + if (rio_cmd.length < 0 || rio_cmd.length > PAGE_SIZE) { retval = -EINVAL; goto err_out; } diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c --- a/drivers/usb/misc/tiglusb.c Wed Jul 24 14:03:35 2002 +++ b/drivers/usb/misc/tiglusb.c Wed Jul 24 14:03:35 2002 @@ -2,18 +2,29 @@ * * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver. * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org). - * - * Copyright (C) 2001-2002: + * + * Copyright (C) 2001-2002: * Romain Lievin * Julien BLACHE * under the terms of the GNU General Public License. * * Based on dabusb.c, printer.c & scanner.c * - * Please see the file: linux/Documentation/usb/SilverLink.txt + * Please see the file: linux/Documentation/usb/SilverLink.txt * and the website at: http://lpg.ticalc.org/prj_usb/ * for more info. * + * History : + * 16/07/2002 : v1.04 -- Julien BLACHE + * + removed useless usblp_cleanup() + * + removed {un,}lock_kernel() as suggested on lkml + * + inlined clear_pipes() (used once) + * + inlined clear_device() (small, used twice) + * + removed tiglusb_find_struct() (used once, simple code) + * + replaced down() with down_interruptible() wherever possible + * + fixed double unregistering wrt devfs, causing devfs + * to force an oops when the device is deconnected + * + removed unused fields from struct tiglusb_t */ #include @@ -30,15 +41,18 @@ #include #include "tiglusb.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +# define minor(x) MINOR(x) +#endif + /* * Version Information */ -#define DRIVER_VERSION "1.03" +#define DRIVER_VERSION "1.04" #define DRIVER_AUTHOR "Romain Lievin & Julien Blache " #define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver" #define DRIVER_LICENSE "GPL" - /* ----- global variables --------------------------------------------- */ static tiglusb_t tiglusb[MAXTIGL]; @@ -48,48 +62,47 @@ /*---------- misc functions ------------------------------------------- */ -/* Unregister device */ -static void usblp_cleanup (tiglusb_t * s) -{ - devfs_unregister (s->devfs); - //memset(tiglusb[s->minor], 0, sizeof(tiglusb_t)); - info ("tiglusb%d removed", s->minor); -} - -/* Re-initialize device */ -static int clear_device (struct usb_device *dev) +/* + * Re-initialize device + */ +static inline int +clear_device (struct usb_device *dev) { if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) { - err ("tiglusb: clear_device failed"); + err ("clear_device failed"); return -1; } return 0; } -/* Clear input & output pipes (endpoints) */ -static int clear_pipes (struct usb_device *dev) +/* + * Clear input & output pipes (endpoints) + */ +static inline int +clear_pipes (struct usb_device *dev) { unsigned int pipe; pipe = usb_sndbulkpipe (dev, 1); if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) { - err("tiglusb: clear_pipe (r), request failed"); + err ("clear_pipe (r), request failed"); return -1; } pipe = usb_sndbulkpipe (dev, 2); if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) { - err ("tiglusb: clear_pipe (w), request failed"); + err ("clear_pipe (w), request failed"); return -1; } return 0; } -/* ----- kernel module functions--------------------------------------- */ +/* ----- file operations functions--------------------------------------- */ -static int tiglusb_open (struct inode *inode, struct file *file) +static int +tiglusb_open (struct inode *inode, struct file *filp) { int devnum = minor (inode->i_rdev); ptiglusb_t s; @@ -99,37 +112,46 @@ s = &tiglusb[devnum - TIUSB_MINOR]; - down (&s->mutex); + if (down_interruptible (&s->mutex)) { + return -ERESTARTSYS; + } while (!s->dev || s->opened) { up (&s->mutex); - if (file->f_flags & O_NONBLOCK) { + if (filp->f_flags & O_NONBLOCK) { return -EBUSY; } + schedule_timeout (HZ / 2); if (signal_pending (current)) { return -EAGAIN; } - down (&s->mutex); + + if (down_interruptible (&s->mutex)) { + return -ERESTARTSYS; + } } s->opened = 1; up (&s->mutex); - file->f_pos = 0; - file->private_data = s; + filp->f_pos = 0; + filp->private_data = s; return 0; } -static int tiglusb_release (struct inode *inode, struct file *file) +static int +tiglusb_release (struct inode *inode, struct file *filp) { - ptiglusb_t s = (ptiglusb_t) file->private_data; + ptiglusb_t s = (ptiglusb_t) filp->private_data; + + if (down_interruptible (&s->mutex)) { + return -ERESTARTSYS; + } - lock_kernel (); - down (&s->mutex); s->state = _stopped; up (&s->mutex); @@ -139,14 +161,14 @@ wake_up (&s->remove_ok); s->opened = 0; - unlock_kernel (); return 0; } -static ssize_t tiglusb_read (struct file *file, char *buf, size_t count, loff_t * ppos) +static ssize_t +tiglusb_read (struct file *filp, char *buf, size_t count, loff_t * f_pos) { - ptiglusb_t s = (ptiglusb_t) file->private_data; + ptiglusb_t s = (ptiglusb_t) filp->private_data; ssize_t ret = 0; int bytes_to_read = 0; int bytes_read = 0; @@ -154,7 +176,7 @@ char buffer[BULK_RCV_MAX]; unsigned int pipe; - if (*ppos) + if (*f_pos) return -ESPIPE; if (s->remove_pending) @@ -171,35 +193,35 @@ if (result == -ETIMEDOUT) { /* NAK */ ret = result; if (!bytes_read) { - warn ("quirk !"); + dbg ("quirk !"); } warn ("tiglusb_read, NAK received."); goto out; } else if (result == -EPIPE) { /* STALL -- shouldn't happen */ - warn ("CLEAR_FEATURE request to remove STALL condition.\n"); + warn ("clear_halt request to remove STALL condition."); if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe))) - warn ("send_packet, request failed\n"); - //clear_device(s->dev); + err ("clear_halt, request failed"); + clear_device (s->dev); ret = result; goto out; } else if (result < 0) { /* We should not get any I/O errors */ - warn ("funky result: %d. Please notify maintainer.", result); + err ("funky result: %d. Please notify maintainer.", result); ret = -EIO; goto out; } if (copy_to_user (buf, buffer, bytes_read)) { ret = -EFAULT; - goto out; } out: return ret ? ret : bytes_read; } -static ssize_t tiglusb_write (struct file *file, const char *buf, size_t count, loff_t * ppos) +static ssize_t +tiglusb_write (struct file *filp, const char *buf, size_t count, loff_t * f_pos) { - ptiglusb_t s = (ptiglusb_t) file->private_data; + ptiglusb_t s = (ptiglusb_t) filp->private_data; ssize_t ret = 0; int bytes_to_write = 0; int bytes_written = 0; @@ -207,7 +229,7 @@ char buffer[BULK_SND_MAX]; unsigned int pipe; - if (*ppos) + if (*f_pos) return -ESPIPE; if (s->remove_pending) @@ -231,10 +253,10 @@ ret = result; goto out; } else if (result == -EPIPE) { /* STALL -- shouldn't happen */ - warn ("CLEAR_FEATURE request to remove STALL condition."); + warn ("clear_halt request to remove STALL condition."); if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe))) - warn ("send_packet, request failed"); - //clear_device(s->dev); + err ("clear_halt, request failed"); + clear_device (s->dev); ret = result; goto out; } else if (result < 0) { /* We should not get any I/O errors */ @@ -245,23 +267,25 @@ if (bytes_written != bytes_to_write) { ret = -EIO; - goto out; } out: return ret ? ret : bytes_written; } -static int tiglusb_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int +tiglusb_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - ptiglusb_t s = (ptiglusb_t) file->private_data; + ptiglusb_t s = (ptiglusb_t) filp->private_data; int ret = 0; if (s->remove_pending) return -EIO; - down (&s->mutex); + if (down_interruptible (&s->mutex)) { + return -ERESTARTSYS; + } if (!s->dev) { up (&s->mutex); @@ -304,40 +328,30 @@ .release = tiglusb_release, }; -static int tiglusb_find_struct (void) -{ - int u; - - for (u = 0; u < MAXTIGL; u++) { - ptiglusb_t s = &tiglusb[u]; - if (!s->dev) - return u; - } - - return -1; -} - /* --- initialisation code ------------------------------------- */ -static void *tiglusb_probe (struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) +static void * +tiglusb_probe (struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { - int minor; + int minor = -1; + int i; ptiglusb_t s; char name[8]; - dbg ("tiglusb: probing vendor id 0x%x, device id 0x%x ifnum:%d", + dbg ("probing vendor id 0x%x, device id 0x%x ifnum:%d", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); - /* - * We don't handle multiple configurations. As of version 0x0103 of - * the TIGL hardware, there's only 1 configuration. + /* + * We don't handle multiple configurations. As of version 0x0103 of + * the TIGL hardware, there's only 1 configuration. */ if (dev->descriptor.bNumConfigurations != 1) return NULL; - if ((dev->descriptor.idProduct != 0xe001) && (dev->descriptor.idVendor != 0x451)) + if ((dev->descriptor.idProduct != 0xe001) + && (dev->descriptor.idVendor != 0x451)) return NULL; if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) { @@ -345,7 +359,17 @@ return NULL; } - minor = tiglusb_find_struct (); + /* + * Find a tiglusb struct + */ + for (i = 0; i < MAXTIGL; i++) { + ptiglusb_t s = &tiglusb[i]; + if (!s->dev) { + minor = i; + break; + } + } + if (minor == -1) return NULL; @@ -358,26 +382,28 @@ dbg ("bound to interface: %d", ifnum); sprintf (name, "%d", s->minor); - info ("tiglusb: registering to devfs : major = %d, minor = %d, node = %s", TIUSB_MAJOR, - (TIUSB_MINOR + s->minor), name); + dbg ("registering to devfs : major = %d, minor = %d, node = %s", + TIUSB_MAJOR, (TIUSB_MINOR + s->minor), name); s->devfs = devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, TIUSB_MAJOR, - TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO, &tiglusb_fops, - NULL); + TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO, + &tiglusb_fops, NULL); /* Display firmware version */ - info ("tiglusb: link cable version %i.%02x", - dev->descriptor.bcdDevice >> 8, dev->descriptor.bcdDevice & 0xff); + info ("link cable version %i.%02x", + dev->descriptor.bcdDevice >> 8, + dev->descriptor.bcdDevice & 0xff); return s; } -static void tiglusb_disconnect (struct usb_device *dev, void *drv_context) +static void +tiglusb_disconnect (struct usb_device *dev, void *drv_context) { ptiglusb_t s = (ptiglusb_t) drv_context; if (!s || !s->dev) - warn ("bogus disconnect"); + info ("bogus disconnect"); s->remove_pending = 1; wake_up (&s->wait); @@ -387,16 +413,12 @@ s->dev = NULL; s->opened = 0; - /* cleanup now or later, on close */ - if (!s->opened) - usblp_cleanup (s); - else - up (&s->mutex); - - /* unregister device */ devfs_unregister (s->devfs); s->devfs = NULL; - info ("tiglusb: device disconnected"); + + info ("device %d removed", s->minor); + + up (&s->mutex); } static struct usb_device_id tiglusb_ids[] = { @@ -417,9 +439,11 @@ /* --- initialisation code ------------------------------------- */ #ifndef MODULE -/* You must set these - there is no sane way to probe for this cable. - * You can use 'tipar=timeout,delay' to set these now. */ -static int __init tiglusb_setup (char *str) +/* + * You can use 'tiusb=timeout' + */ +static int __init +tiglusb_setup (char *str) { int ints[2]; @@ -433,7 +457,8 @@ } #endif -static int __init tiglusb_init (void) +static int __init +tiglusb_init (void) { unsigned u; int result; @@ -452,7 +477,7 @@ /* register device */ if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) { - err ("tiglusb: unable to get major %d", TIUSB_MAJOR); + err ("unable to get major %d", TIUSB_MAJOR); return -EIO; } @@ -471,7 +496,8 @@ return 0; } -static void __exit tiglusb_cleanup (void) +static void __exit +tiglusb_cleanup (void) { usb_deregister (&tiglusb_driver); devfs_unregister (devfs_handle); diff -Nru a/drivers/usb/misc/tiglusb.h b/drivers/usb/misc/tiglusb.h --- a/drivers/usb/misc/tiglusb.h Wed Jul 24 14:03:39 2002 +++ b/drivers/usb/misc/tiglusb.h Wed Jul 24 14:03:39 2002 @@ -33,7 +33,6 @@ { struct usb_device *dev; /* USB device handle */ struct semaphore mutex; /* locks this struct */ - struct semaphore sem; wait_queue_head_t wait; /* for timed waits */ wait_queue_head_t remove_ok; @@ -44,12 +43,6 @@ driver_state_t state; /* started/stopped */ int opened; /* tru if open */ int remove_pending; - - char rd_buf[BULK_RCV_MAX]; /* read buffer */ - char wr_buf[BULK_SND_MAX]; /* write buffer */ - } tiglusb_t, *ptiglusb_t; - -extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ #endif diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/net/rtl8150.c Wed Jul 24 14:03:38 2002 @@ -21,7 +21,7 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.5.4 (2002/04/11)" +#define DRIVER_VERSION "v0.5.5 (2002/07/22)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" @@ -68,11 +68,15 @@ /* Define these values to match your device */ #define VENDOR_ID_REALTEK 0x0bda +#define VENDOR_ID_MELCO 0x0411 + #define PRODUCT_ID_RTL8150 0x8150 +#define PRODUCT_ID_LUAKTX 0x0012 /* table of devices that work with this driver */ static struct usb_device_id rtl8150_table[] = { {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)}, + {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, {} }; @@ -727,11 +731,6 @@ if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) { err("usb_set_configuration() failed"); - return NULL; - } - if ((udev->descriptor.idVendor != VENDOR_ID_REALTEK) || - (udev->descriptor.idProduct != PRODUCT_ID_RTL8150)) { - err("Not the one we are interested about"); return NULL; } dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL); diff -Nru a/drivers/usb/serial/keyspan_pda.S b/drivers/usb/serial/keyspan_pda.S --- a/drivers/usb/serial/keyspan_pda.S Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/serial/keyspan_pda.S Wed Jul 24 14:03:38 2002 @@ -970,9 +970,9 @@ mov r1, #1 ; INbuf size counter start_in__loop: mov a, rx_ring_in - cjne a, rx_ring_out, start_in__still_copying + cjne a, rx_ring_out, start_inlocal_irq_enablell_copying sjmp start_in__kick -start_in__still_copying: +start_inlocal_irq_enablell_copying: inc rx_ring_out mov dpl, rx_ring_out movx a, @dptr diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/serial/pl2303.c Wed Jul 24 14:03:38 2002 @@ -71,6 +71,7 @@ { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, + { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h --- a/drivers/usb/serial/pl2303.h Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/serial/pl2303.h Wed Jul 24 14:03:38 2002 @@ -19,3 +19,6 @@ #define ELCOM_VENDOR_ID 0x056e #define ELCOM_PRODUCT_ID 0x5003 + +#define ITEGNO_VENDOR_ID 0x0eba +#define ITEGNO_PRODUCT_ID 0x1080 diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h --- a/drivers/usb/serial/usb-serial.h Wed Jul 24 14:03:38 2002 +++ b/drivers/usb/serial/usb-serial.h Wed Jul 24 14:03:38 2002 @@ -67,11 +67,40 @@ /* parity check flag */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - +/** + * usb_serial_port: structure for the specific ports of a device. + * @magic: magic number for internal validity of this pointer. + * @serial: pointer back to the struct usb_serial owner of this port. + * @tty: pointer to the coresponding tty for this port. + * @number: the number of the port (the minor number). + * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. + * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. + * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe + * for this port. + * @bulk_in_buffer: pointer to the bulk in buffer for this port. + * @read_urb: pointer to the bulk in struct urb for this port. + * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this + * port. + * @bulk_out_buffer: pointer to the bulk out buffer for this port. + * @bulk_out_size: the size of the bulk_out_buffer, in bytes. + * @write_urb: pointer to the bulk out struct urb for this port. + * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this + * port. + * @write_wait: a wait_queue_head_t used by the port. + * @tqueue: task queue for the line discipline waking up. + * @open_count: number of times this port has been opened. + * @sem: struct semaphore used to lock this structure. + * @private: place to put any driver specific information that is needed. The + * usb-serial driver is required to manage this data, the usb-serial core + * will not touch this. + * + * This structure is used by the usb-serial core and drivers for the specific + * ports of a device. + */ struct usb_serial_port { int magic; - struct usb_serial *serial; /* pointer back to the owner of this port */ - struct tty_struct * tty; /* the coresponding tty for this port */ + struct usb_serial *serial; + struct tty_struct * tty; unsigned char number; unsigned char * interrupt_in_buffer; @@ -88,30 +117,44 @@ __u8 bulk_out_endpointAddress; wait_queue_head_t write_wait; - - struct tq_struct tqueue; /* task queue for line discipline waking up */ - int open_count; /* number of times this port has been opened */ - struct semaphore sem; /* locks this structure */ - - void * private; /* data private to the specific port */ + struct tq_struct tqueue; + int open_count; + struct semaphore sem; + void * private; }; +/** + * usb_serial - structure used by the usb-serial core for a device + * @magic: magic number for internal validity of this pointer. + * @dev: pointer to the struct usb_device for this device + * @type: pointer to the struct usb_serial_device_type for this device + * @interface: pointer to the struct usb_interface for this device + * @minor: the starting minor number for this device + * @num_ports: the number of ports this device has + * @num_interrupt_in: number of interrupt in endpoints we have + * @num_bulk_in: number of bulk in endpoints we have + * @num_bulk_out: number of bulk out endpoints we have + * @vendor: vendor id of this device + * @product: product id of this device + * @port: array of struct usb_serial_port structures for the different ports. + * @private: place to put any driver specific information that is needed. The + * usb-serial driver is required to manage this data, the usb-serial core + * will not touch this. + */ struct usb_serial { int magic; struct usb_device * dev; - struct usb_serial_device_type * type; /* the type of usb serial device this is */ - struct usb_interface * interface; /* the interface for this device */ - struct tty_driver * tty_driver; /* the tty_driver for this device */ - unsigned char minor; /* the starting minor number for this device */ - unsigned char num_ports; /* the number of ports this device has */ - char num_interrupt_in; /* number of interrupt in endpoints we have */ - char num_bulk_in; /* number of bulk in endpoints we have */ - char num_bulk_out; /* number of bulk out endpoints we have */ - __u16 vendor; /* vendor id of this device */ - __u16 product; /* product id of this device */ + struct usb_serial_device_type * type; + struct usb_interface * interface; + unsigned char minor; + unsigned char num_ports; + char num_interrupt_in; + char num_bulk_in; + char num_bulk_out; + __u16 vendor; + __u16 product; struct usb_serial_port port[MAX_NUM_PORTS]; - - void * private; /* data private to the specific driver */ + void * private; }; diff -Nru a/drivers/usb/serial/xircom_pgs.S b/drivers/usb/serial/xircom_pgs.S --- a/drivers/usb/serial/xircom_pgs.S Wed Jul 24 14:03:35 2002 +++ b/drivers/usb/serial/xircom_pgs.S Wed Jul 24 14:03:35 2002 @@ -1035,9 +1035,9 @@ mov r1, #1 ; INbuf size counter start_in__loop: mov a, rx_ring_in - cjne a, rx_ring_out, start_in__still_copying + cjne a, rx_ring_out, start_inlocal_irq_enablell_copying sjmp start_in__kick -start_in__still_copying: +start_inlocal_irq_enablell_copying: inc rx_ring_out mov dpl, rx_ring_out movx a, @dptr diff -Nru a/drivers/video/Config.help b/drivers/video/Config.help --- a/drivers/video/Config.help Wed Jul 24 14:03:36 2002 +++ b/drivers/video/Config.help Wed Jul 24 14:03:36 2002 @@ -77,6 +77,12 @@ module will be called amifb.o. If you want to compile it as a module, say M here and read . +CONFIG_FB_PM3 + This is the frame buffer device driver for the 3DLabs Permedia3 + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 + and maybe other boards. + CONFIG_FB_AMIGA_OCS This enables support for the original Agnus and Denise video chips, found in the Amiga 1000 and most A500's and A2000's. If you intend @@ -587,6 +593,12 @@ The IMS Twin Turbo is a PCI-based frame buffer card bundled with many Macintosh and compatible computers. +CONFIG_FB_TX3912 + The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core + see . + + Say Y here to enable kernel support for the on-board framebuffer. + CONFIG_FB_VIRTUAL This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics @@ -704,17 +716,7 @@ This is the low level frame buffer console driver for 8 interleaved bitplanes (256 colors) on Atari. -CONFIG_FBCON_MAC - This is the low level frame buffer console driver for 1/2/4/8/16/32 - bits per pixel packed pixels on Mac. It supports variable font - widths for low resolution screens. - CONFIG_FBCON_HGA This is the low level frame buffer console driver for Hercules mono graphics cards. - -CONFIG_FBCON_VGA - This is the low level frame buffer console driver for VGA text mode; - it is used by frame buffer device drivers that support VGA text - mode. diff -Nru a/drivers/video/Config.in b/drivers/video/Config.in --- a/drivers/video/Config.in Wed Jul 24 14:03:38 2002 +++ b/drivers/video/Config.in Wed Jul 24 14:03:38 2002 @@ -108,6 +108,7 @@ bool ' Sun3 framebuffer support' CONFIG_FB_SUN3 if [ "$CONFIG_FB_SUN3" != "n" ]; then bool ' BWtwo support' CONFIG_FB_BWTWO + bool ' CGthree support' CONFIG_FB_CGTHREE bool ' CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX fi fi @@ -227,41 +228,35 @@ tristate ' Atari interleaved bitplanes (4 planes) support' CONFIG_FBCON_IPLAN2P4 tristate ' Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 # tristate ' Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 - tristate ' Mac variable bpp packed pixels support' CONFIG_FBCON_MAC tristate ' VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES - tristate ' VGA characters/attributes support' CONFIG_FBCON_VGA tristate ' HGA monochrome support (EXPERIMENTAL)' CONFIG_FBCON_HGA else # Guess what we need if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_AMIGA" = "y" -o \ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ - "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ - "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ - "$CONFIG_FB_BWTWO" = "y" ]; then + "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ + "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then define_tristate CONFIG_FBCON_MFB y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ - "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ - "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ - "$CONFIG_FB_BWTWO" = "m" ]; then + "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ + "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then define_tristate CONFIG_FBCON_MFB m fi fi - if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ - "$CONFIG_FB_SA1100" = "y" ]; then + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then define_tristate CONFIG_FBCON_CFB2 y define_tristate CONFIG_FBCON_CFB4 y else - if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" ]; then + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_SA1100" = "m"]; then define_tristate CONFIG_FBCON_CFB2 m define_tristate CONFIG_FBCON_CFB4 m fi fi if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \ - "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ - "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ + "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ + "$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ @@ -270,15 +265,12 @@ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ - "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ - "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ - "$CONFIG_FB_SA1100" = "y" ]; then + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ - "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ - "$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ + "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ + "$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ "$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ @@ -286,40 +278,33 @@ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ - "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ - "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ - "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" ]; then + "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m"-o \ + "$CONFIG_FB_SA1100" = "m" ]; then define_tristate CONFIG_FBCON_CFB8 m fi fi - if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ - "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ + if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ + "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ "$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ - "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \ - "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ - "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then + "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then define_tristate CONFIG_FBCON_CFB16 y else - if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ - "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ + if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ + "$CONFIG_FB_RADEON" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ "$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ - "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ - "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ - "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then + "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ + "$CONFIG_FB_SA1100" = "y" ]; then define_tristate CONFIG_FBCON_CFB16 m fi fi @@ -340,26 +325,22 @@ define_tristate CONFIG_FBCON_CFB24 m fi fi - if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ + if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ - "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ - "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \ - "$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \ - "$CONFIG_FB_PM3" = "y" ]; then + "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ + "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_ATY" = "y" ]; then define_tristate CONFIG_FBCON_CFB32 y else - if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ + if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ - "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ - "$CONFIG_FB_PM3" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ - "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ - "$CONFIG_FB_PVR2" = "m" ]; then + "$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \ + "$CONFIG_FB_PM3" = "m" ]; then define_tristate CONFIG_FBCON_CFB32 m fi fi @@ -370,12 +351,16 @@ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \ "$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \ - "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" ]; then + "$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o \ + "$CONFIG_FB_ATY128" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_OF" = "y" -o \ + "$CONFIG_FB_SGIVW" = "y" ]; then define_tristate CONFIG_FBCON_ACCEL y else if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \ "$CONFIG_FB_G364" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ - "$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" ]; then + "$CONFIG_FB_CLPS711X" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ + "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_SGIVW" = "m" ]; then define_tristate CONFIG_FBCON_ACCEL m fi fi @@ -392,20 +377,11 @@ define_tristate CONFIG_FBCON_IPLAN2P2 y define_tristate CONFIG_FBCON_IPLAN2P4 y define_tristate CONFIG_FBCON_IPLAN2P8 y -# define_tristate CONFIG_FBCON_IPLAN2P16 y else if [ "$CONFIG_FB_ATARI" = "m" ]; then define_tristate CONFIG_FBCON_IPLAN2P2 m define_tristate CONFIG_FBCON_IPLAN2P4 m define_tristate CONFIG_FBCON_IPLAN2P8 m -# define_tristate CONFIG_FBCON_IPLAN2P16 m - fi - fi - if [ "$CONFIG_FB_MAC" = "y" ]; then - define_tristate CONFIG_FBCON_MAC y - else - if [ "$CONFIG_FB_MAC" = "m" ]; then - define_tristate CONFIG_FBCON_MAC m fi fi if [ "$CONFIG_FB_VGA16" = "y" ]; then diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Wed Jul 24 14:03:36 2002 +++ b/drivers/video/Makefile Wed Jul 24 14:03:36 2002 @@ -10,8 +10,8 @@ fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \ fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \ fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \ - fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \ - cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o + fbcon-cfb8.o fbcon-mfb.o fbcon-hga.o \ + cyber2000fb.o sa1100fb.o fbgen.o # Each configuration option enables a list of files. @@ -56,9 +56,9 @@ obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CYBER) += cyberfb.o obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o -obj-$(CONFIG_FB_SGIVW) += sgivwfb.o +obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o -obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o +obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o @@ -114,10 +114,7 @@ obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o -obj-$(CONFIG_FBCON_IPLAN2P16) += fbcon-iplan2p16.o -obj-$(CONFIG_FBCON_MAC) += fbcon-mac.o obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o -obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o obj-$(CONFIG_FBCON_STI) += fbcon-sti.o obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o diff -Nru a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c --- a/drivers/video/S3triofb.c Wed Jul 24 14:03:38 2002 +++ b/drivers/video/S3triofb.c Wed Jul 24 14:03:38 2002 @@ -41,9 +41,6 @@ #include #include #include -#ifdef CONFIG_FB_COMPAT_XPMAC -#include -#endif #include