E: nigel@nrg.org
E: nigel@sgi.com
D: Interrupt-driven printer driver
-S: 765 N Rengstorff Ave, Apartment 7
-S: Mountain View, California 94043-2420
+S: 120 Alley Way
+S: Mountain View, California 94040
S: USA
N: Jacques Gelinas
S: Germany
N: Mark Lord
-E: mlord@bnr.ca
+E: mlord@pobox.com
D: Author of IDE driver (ide.c), hd.c support
D: Triton Bus Master IDE driver
D: Hard Disk Parameter (hdparm) utility
S: MacGregor A.C.T
S: 2615 Australia
+N: Winfried Trümper
+E: truemper@MI.Uni-Koeln.DE
+D: German HOWTO, Enhanced German HOWTO, Crash-Kurs Linux (German)
+D: 1- or 5-days tutorials on Linux twice a year (free of charge)
+D: Linux-Workshop Köln (aka LUUG cologne, germany)
+S: Tacitusstr. 6
+S: D-50968 Köln
+
N: Theodore Ts'o
E: tytso@mit.edu
D: Random Linux hacker
RAM disk support
CONFIG_BLK_DEV_RAM
- Enabling this option will allow you to use a portion of your RAM memory
- as a block device, so that you can make filesystems on it, read and
- write to it and do all the other things that normal block devices can do.
- It is usually used to load and store a copy of a minimal root file
- system off of a floppy into RAM during the initial install of Linux.
- Note that the kernel command line option "ramdisk=XX" is now obsolete.
- For details, read Documentation/ramdisk.txt. If you want to compile this
- as a module ( = code which can be inserted in and removed from the
- running kernel whenever you want), say M and read Documentation/modules.txt.
- Most normal users won't need the RAM disk functionality, and can thus say
+ Enabling this option will allow you to use a portion of your RAM
+ memory as a block device, so that you can make filesystems on it,
+ read and write to it and do all the other things that normal block
+ devices (such as harddrives) can do. It is usually used to load and
+ store a copy of a minimal root file system off of a floppy into RAM
+ during the initial install of Linux. Note that the kernel command
+ line option "ramdisk=XX" is now obsolete. For details, read
+ Documentation/ramdisk.txt. If you want to compile this as a module (
+ = code which can be inserted in and removed from the running kernel
+ whenever you want), say M and read Documentation/modules.txt. Most
+ normal users won't need the RAM disk functionality, and can thus say
N here.
Loop device support
burning the CD, or want to use floppy images without first writing
them to floppy.
This option also allows one to mount a filesystem with encryption.
+ To use these features, you will need the program losetup, available
+ via ftp (user: anonymous) from sunsite.unc.edu in the package
+ lo.X.Y.tar.gz.
+ Note that this loop device has nothing to do with the loopback
+ device used for network connections from the machine to itself.
Most users will answer N here.
Enhanced IDE/MFM/RLL disk/cdrom/tape support
CONFIG_BLK_DEV_IDE
This will use the full-featured IDE driver to control up to four IDE
- interfaces, for a combination of up to eight IDE disk/cdrom/tape drives.
- Useful information about large (>540MB) IDE disks, soundcard IDE ports,
- and other topics, is all contained in drivers/block/README.ide.
- If you have one or more IDE drives, say Y here.
- If your system has no IDE drives, or if memory requirements are really tight,
- you could say N here, and select the Old harddisk driver instead to save
- about 13kB of memory in the kernel.
- To fine-tune IDE drive/interface parameters for improved performance,
+ interfaces, for a combination of up to eight IDE disk/cdrom/tape
+ drives. Useful information about large (>540MB) IDE disks,
+ soundcard IDE ports, and other topics, is all contained in
+ drivers/block/README.ide. If you have one or more IDE drives, say Y
+ here. If your system has no IDE drives, or if memory requirements
+ are really tight, you could say N here, and select the Old harddisk
+ driver instead to save about 13kB of memory in the kernel. To
+ fine-tune IDE drive/interface parameters for improved performance,
look for the hdparm package at
sunsite.unc.edu:/pub/Linux/kernel/patches/diskdrives/
Old harddisk (MFM/RLL/IDE) driver
CONFIG_BLK_DEV_HD_ONLY
There are two drivers for MFM/RLL/IDE disks. Most people use the
- newer enhanced driver, but the old one is still around for two reasons.
- Some older systems have strange timing problems and seem to work only
- with the old driver (which itself does not work with some newer systems).
- The other reason is that the old driver is smaller, since it lacks the
- enhanced functionality of the new one. This makes it a good choice
- for systems with very tight memory restrictions, or for systems with
- only older MFM/RLL/ESDI drives. Choosing the old driver can save 13kB
- or so of kernel memory. If you are unsure, then just choose the
- Enhanced IDE/MFM/RLL driver instead of this one.
+ newer enhanced driver, but the old one is still around for two
+ reasons. Some older systems have strange timing problems and seem
+ to work only with the old driver (which itself does not work with
+ some newer systems). The other reason is that the old driver is
+ smaller, since it lacks the enhanced functionality of the new one.
+ This makes it a good choice for systems with very tight memory
+ restrictions, or for systems with only older MFM/RLL/ESDI drives.
+ Choosing the old driver can save 13kB or so of kernel memory. If
+ you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
+ instead of this one.
Use old disk-only driver on primary interface
CONFIG_BLK_DEV_HD_IDE
- There are two drivers for MFM/RLL/IDE disks. Most people use just the
- new enhanced driver by itself. This option installs the old harddisk
- driver to control the primary IDE/disk interface in the system,
- leaving the new enhanced IDE driver take care of only the 2nd/3rd/4th
- IDE interfaces. Choosing this option may be useful for older systems
- which have MFM/RLL/ESDI controller+drives at the primary port address
- (0x1f0), along with IDE drives at the secondary/3rd/4th port addresses.
- Normally, just say N here.
+ There are two drivers for MFM/RLL/IDE disks. Most people use just
+ the new enhanced driver by itself. This option installs the old
+ harddisk driver to control the primary IDE/disk interface in the
+ system, leaving the new enhanced IDE driver take care of only the
+ 2nd/3rd/4th IDE interfaces. Choosing this option may be useful for
+ older systems which have MFM/RLL/ESDI controller+drives at the
+ primary port address (0x1f0), along with IDE drives at the
+ secondary/3rd/4th port addresses. Normally, just say N here; you
+ will then use the new driver for all 4 interfaces.
Include IDE/ATAPI CDROM support
CONFIG_BLK_DEV_IDECD
- If you have a CDROM drive using the ATAPI protocol, say Y.
- ATAPI is a new protocol used by IDE CDROM and TAPE drives,
- similar to the SCSI protocol. Most new CDROM drives use ATAPI,
- including the NEC-260, Mitsumi FX400, Sony 55E, and just about
- all non-SCSI double(2X), quad(4X), and six(6X) speed drives.
- At boot time, the TAPE drive will be identified along with other IDE devices,
- as "hdb" or "hdc", or something similar.
- If this is your only CDROM drive, you can say N to all other CDROM options,
- but be sure to say Y to the ISO9660 filesystem. Read the CDROM-HOWTO,
- available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO.
- Note that older versions of lilo (the linux boot loader) cannot properly
- deal with IDE/ATAPI CDROMs, so install lilo-16 or higher, available
- from sunsite.unc.edu:/pub/Linux/system/Linux-boot/lilo.
+ If you have a CDROM drive using the ATAPI protocol, say Y. ATAPI is
+ a new protocol used by IDE CDROM and TAPE drives, similar to the
+ SCSI protocol. Most new CDROM drives use ATAPI, including the
+ NEC-260, Mitsumi FX400, Sony 55E, and just about all non-SCSI
+ double(2X), quad(4X), and six(6X) speed drives. At boot time, the
+ TAPE drive will be identified along with other IDE devices, as "hdb"
+ or "hdc", or something similar.
+ If this is your only CDROM drive, you can say N to all other CDROM
+ options, but be sure to say Y to the ISO9660 filesystem. Read the
+ CDROM-HOWTO, available via ftp (user: anonymous) in
+ sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that older versions of
+ lilo (the linux boot loader) cannot properly deal with IDE/ATAPI
+ CDROMs, so install lilo-16 or higher, available from
+ sunsite.unc.edu:/pub/Linux/system/Linux-boot/lilo.
Include IDE/ATAPI TAPE support
CONFIG_BLK_DEV_IDETAPE
chipsets. Most of these also require special kernel boot parameters
to actually turn on the support at runtime.
-DTC-2278 chipset support
+DTC-2278 support
CONFIG_BLK_DEV_DTC2278
This driver is enabled at runtime using the "ide0=dtc2278" kernel
boot parameter. It enables support for the secondary IDE interface
of the DTC-2278 card, and permits faster I/O speeds to be set as
well. See the README.ide and dtc2278.c files for more info.
-Holtek HT6560B chipset support
+Holtek HT6560B support
CONFIG_BLK_DEV_HT6560B
This driver is enabled at runtime using the "ide0=ht6560b" kernel
boot parameter. It enables support for the secondary IDE interface
of the Holtek card, and permits faster I/O speeds to be set as well.
See the README.ide and ht6560b.c files for more info.
-QDI QD6580 chipset support
+QDI QD6580 support
CONFIG_BLK_DEV_QD6580
This driver is enabled at runtime using the "ide0=qd6580" kernel
boot parameter. It permits faster I/O speeds to be set.
See the README.ide and qd6580.c files for more info.
-UMC 8672 chipset support
+UMC 8672 support
CONFIG_BLK_DEV_UMC8672
This driver is enabled at runtime using the "ide0=umc8672" kernel
boot parameter. It enables support for the secondary IDE interface
of the UMC-8672, and permits faster I/O speeds to be set as well.
See the README.ide and umc8672.c files for more info.
-ALI M1439/M1445 chipset support
+ALI M1439/M1445 support
CONFIG_BLK_DEV_ALI14XX
This driver is enabled at runtime using the "ide0=ali14xx" kernel
boot parameter. It enables support for the secondary IDE interface
If your compiler is mipsel-linux-gcc or mipsel-linuxelf-gcc (as
opposed to mips-linux-gcc or mips-linuxelf-gcc), say Y here,
otherwise N. Most MIPS machines use little-endian code, but it might
- be necessary to run older Mips sytems, such as the Sony News and
+ be necessary to run older Mips systems, such as the Sony News and
MIPS RC3xxx in big endian mode.
Enable loadable module support
drivers/net/README.multicast. For most people, it's safe to say N.
IP: optimize as router not host
+CONFIG_IP_ROUTER
Some Linux network drivers use a technique called copy and checksum
to optimize host performance. For a machine which is forwarding most
packets to another host this is however a loss. This parameter turns
sunsite.unc.edu:/pub/Linux/docs/HOWTO). In order to do the former,
you'll also have to say Y to "NCP filesystem support", below. To
turn your Linux box into a fully featured Netware file server and
- IPX router, say Y here and fetch lwared from
- sunsite.unc.edu:/pub/Linux/system/Network/daemons/. For more
- information, read the IPX-HOWTO in
- sunsite.unc.edu:/pub/Linux/docs/howto. The IPX driver would enlarge
- your kernel by about 5 kB. Unless you want to integrate your Linux
- box with a local Novell network, say N.
+ IPX router, say Y here and fetch either lwared from
+ sunsite.unc.edu:/pub/Linux/system/Network/daemons/ or mars_nwe from
+ linux01.gwdg.de:/pub/ncpfs. For more information, read the IPX-HOWTO
+ in sunsite.unc.edu:/pub/Linux/docs/howto. The IPX driver would
+ enlarge your kernel by about 5 kB. Unless you want to integrate your
+ Linux box with a local Novell network, say N.
Full internal IPX network
CONFIG_IPX_INTERN
CONFIG_NI52
If you have a network (ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available via ftp (user: anonymous) in
- sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available
- as a module ( = code which can be inserted in and removed from the
- running kernel whenever you want). If you want to compile it as a
- module, say M here and read Documentation/modules.txt as well as
- Documentation/networking/net-modules.txt. If you plan to use more
- than one network card under linux, read the
- Multiple-Ethernet-mini-HOWTO, available from
- sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+ sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than
+ one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
+ available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
NI6510 support
CONFIG_NI65
msdos fs support
CONFIG_MSDOS_FS
This allows you to mount MSDOS partitions of your harddrive (unless
- they are compressed; the only way to access compressed MSDOS
- partitions under Linux is with the DOS emulator DOSEMU, described in
- the DOSEMU-HOWTO, available via ftp (user: anonymous) at
- sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you intend to use dosemu
- with a non-compressed MSDOS partition, say Y here) and MSDOS
- floppies. This means that file access becomes transparent, i.e. the
- MSDOS files look and behave just like all other Unix files. Another
- way to read and write MSDOS floppies from within Linux (but not
- transparently) is with the mtools ("man mtools") program suite,
+ they are compressed; to access compressed MSDOS partitions under
+ Linux, you can either use the DOS emulator DOSEMU, described in the
+ DOSEMU-HOWTO, available via ftp (user: anonymous) at
+ sunsite.unc.edu:/pub/Linux/docs/HOWTO, or try dmsdosfs in
+ sunsite.unc.edu:/pub/Linux/system/Filesystems/dosfs. If you intend
+ to use dosemu with a non-compressed MSDOS partition, say Y here) and
+ MSDOS floppies. This means that file access becomes transparent,
+ i.e. the MSDOS files look and behave just like all other Unix files.
+ Another way to read and write MSDOS floppies from within Linux (but
+ not transparently) is with the mtools ("man mtools") program suite,
which doesn't require the msdos filesystem support. If you want to
use umsdos, the Unix-like filesystem on top of DOS, which allows you
to run Linux from within a DOS partition without repartitioning,
- you'll have to say Y or M here. If your have Windows'95 or Windows NT
- installed on your MSDOS partitions, you should use the VFAT
- filesystem instead, or you will not be able to see the long filenames
- generated by Windows'95 / Windows NT. This option will enlarge your
- kernel by about 7 kB. If unsure, say Y. If you want to compile this
- as a module however ( = code which can be inserted in and removed from
- the running kernel whenever you want), say M here and read
- Documentation/modules.txt. Note that the filesystem of your root
- partition cannot be a module.
+ you'll have to say Y or M here. If your have Windows'95 or Windows
+ NT installed on your MSDOS partitions, you should use the VFAT
+ filesystem instead, or you will not be able to see the long
+ filenames generated by Windows'95 / Windows NT. This option will
+ enlarge your kernel by about 7 kB. If unsure, say Y. If you want to
+ compile this as a module however ( = code which can be inserted in
+ and removed from the running kernel whenever you want), say M here
+ and read Documentation/modules.txt. Note that the filesystem of your
+ root partition cannot be a module.
vfat fs support
CONFIG_VFAT_FS
This is a virtual filesystem providing information about the status
of the system. "Virtual" means that it doesn't take any space on
your harddisk: the files are created on the fly when you access
- them. Also, you cannot read the files with less or more: you need to
- use cat. The filesystem is explained in the Kernel Hacker's Guide,
- available via ftp (user: anonymous) in
+ them. Also, you cannot read the files with less: you need to use
+ more or cat. The filesystem is explained in the Kernel Hacker's
+ Guide, available via ftp (user: anonymous) in
sunsite.unc.edu:/pub/Linux/docs/LDP and also on the proc(8) manpage
("man 8 proc"). This option will enlarge your kernel by about 18
kB. It's totally cool; for example, "cat /proc/interrupts" gives
used by NetWare clients to talk to file servers. It is to IPX what
nfs is to tcp/ip, if that helps. Enabling this option allows you to
mount NetWare file server volumes and to access them just like any
- other Unix directory. To actually mount the filesystem, you need a
- special mount program, as described in the IPX-HOWTO on
- sunsite.unc.edu:/pub/Linux/docs/howto. If you want to compile this
- as a module ( = code which can be inserted in and removed from the
- running kernel whenever you want), say M here and read
- Documentation/modules.txt.
+ other Unix directory. For details, please read the file
+ Documentation/filesystems/ncpfs.txt in the kernel source and the
+ IPX-HOWTO on sunsite.unc.edu:/pub/Linux/docs/howto. If you want to
+ compile this as a module ( = code which can be inserted in and
+ removed from the running kernel whenever you want), say M here and
+ read Documentation/modules.txt.
Standard/generic serial support
CONFIG_SERIAL
running kernel whenever you want), say M here and read
Documentation/modules.txt.
-CONFIG_ISTALLION n
+Stallion EC8/64, ONboard, Brumby support
+CONFIG_ISTALLION
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
serial multiport card, say Y here. Make sure to read
drivers/char/README.stallion. To compile it as a module ( = code
plugging in a COM port (9 or 25 pins) which is supported
automatically.
-Selection (cut and paste for virtual consoles)
-CONFIG_SELECTION
- This allows you to use your mouse for moving text on a Linux console
- or even between several virtual consoles. Read about it with "man
- selection". You also need it to run gpm ("general purpose mouse")
- which is a superset of selection. This is explained in the
- Busmouse-HOWTO, available via ftp (user: anonymous) in
- sunsite.unc.edu:/pub/Linux/docs/HOWTO, although selection works fine
- with serial mice, too. Most people say Y unless they run mainly the
- X Window System, which has its own cut-and-paste mechanism. Enabling
- this option enlarges your kernel by about 1 kB. Newer kernels
- contain this code by default and don't have this config option
- anymore.
-
QIC-02 tape support
CONFIG_QIC02_TAPE
If you have a non-SCSI tape drive like that, say Y.
Enable APM features
CONFIG_APM_DO_ENABLE
Enable APM features at boot time. From page 36 of the APM BIOS
- specification: "When disabled, the APM BIOS does not automatically power
- manage devices, enter the Standby State, enter the Suspend State, or take
- power saving steps in response to CPU Idle calls." This driver will make
- CPU Idle calls when Linux is idle (unless this feature is turned off --
- see below). This should always save battery power, but more complicated
- APM features will be dependent on your BIOS implementation. You may need
- to turn this option off if your computer hangs at boot time when using
- APM support, or if it beeps continuously instead of suspending. Turn
- this off if you have a NEC UltraLite Versa 33/C or a Toshiba T400CDT.
- This is off by default since most machines do fine without this feature.
+ specification: "When disabled, the APM BIOS does not automatically
+ power manage devices, enter the Standby State, enter the Suspend
+ State, or take power saving steps in response to CPU Idle calls."
+ This driver will make CPU Idle calls when Linux is idle (unless this
+ feature is turned off -- see below). This should always save
+ battery power, but more complicated APM features will be dependent
+ on your BIOS implementation. You may need to turn this option off
+ if your computer hangs at boot time when using APM support, or if it
+ beeps continuously instead of suspending. Turn this off if you have
+ a NEC UltraLite Versa 33/C or a Toshiba T400CDT. This is off by
+ default since most machines do fine without this feature.
Watchdog Timer Support
CONFIG_WATCHDOG
If you enable this option and create a character special file
/dev/watchdog with major number 10 and minor number 130 using mknod
- ("man mknod"), you will get a software watchdog, i.e.: subsequently
- opening the file and failing to write to it for longer than 1 minute
- will result in rebooting the machine. This could be useful for a
+ ("man mknod"), you will get a watchdog, i.e.: subsequently opening
+ the file and failing to write to it for longer than 1 minute will
+ result in rebooting the machine. This could be useful for a
networked machine that needs to come back online as fast as possible
- after a lock-up. For details, read Documentation/watchdog.txt in the
- kernel source. If unsure, say N.
+ after a lock-up. There's a watchdog implementation entirely in
+ software (which sometimes fail to reboot the machine) and a driver
+ for hardware watchdog boards, which are more robust and can also
+ keep track of the temperature inside your computer. For details,
+ read Documentation/watchdog.txt in the kernel source. If unsure, say
+ N.
Disable watchdog shutdown on close
CONFIG_WATCHDOG_NOWAYOUT
The default watchdog behaviour is to stop the timer if the process
- managing it closes the file. Its always remotely possible that this
- process might get killed. In NOWAYOUT mode you cannot stop the watchdog
- once its begun.
+ managing it closes the file /dev/watchdog. It's always remotely
+ possible that this process might get killed. If you enable this
+ option, the watchdog cannot be stopped once it has been started.
WDT Watchdog timer
CONFIG_WDT
- Drivers for the WDT watchdog timer cards. These are hardware timer boards
- that physically pull the power on and off to recover crashed machines.
- Brutal but _very_ effective.
+ If you have a WDT500P or WDT501P watchdog board, say Y here,
+ otherwise N. It is not possible to probe for this board, which means
+ that you have to set the IO port and IRQ it uses in the kernel
+ source at the top of drivers/char/wdt.c. If you want to compile this
+ as a module ( = code which can be inserted in and removed from the
+ running kernel whenever you want), say M here and read
+ Documentation/modules.txt.
WDT501 features
CONFIG_WDT_501
- Enable the onboard thermometer and voltage monitors on the extended (501)
- card.
+ Saying Y here and creating a character special file /dev/temperature
+ with major number 10 and minor number 131 ("man mknod") will give
+ you a thermometer inside your computer: reading from
+ /dev/temperature yields one byte, the temperature in degrees
+ Fahrenheit. This works only if you have a WDT501P watchdog board
+ installed.
Fan Tachometer
CONFIG_WDT_501_FAN
tachometer actually set up.
Software Watchdog
-CONFIG_SOFT_WATDHDOG
- A software monitoring watchdog. This will fail to reboot your system from
- some situations that the hardware watchdog will recover from. Equally its
- a lot cheaper to install.
+CONFIG_SOFT_WATCHDOG
+ A software monitoring watchdog. This will fail to reboot your system
+ from some situations that the hardware watchdog will recover
+ from. Equally it's a lot cheaper to install.
Do CPU IDLE calls
CONFIG_APM_CPU_IDLE
- Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop. On
- some machines, this can activate improved power savings, such as a slowed
- CPU clock rate, when the machine is idle. These idle call is made after
- the idle loop has run for some length of time (e.g., 333 mS). On some
- machines, this will cause a hang at boot time or whenever the CPU becomes
- idle. (On machines with more than one CPU, this option does nothing.)
+ Enable calls to APM CPU Idle/CPU Busy inside the kernel's idle loop.
+ On some machines, this can activate improved power savings, such as
+ a slowed CPU clock rate, when the machine is idle. These idle call
+ is made after the idle loop has run for some length of time (e.g.,
+ 333 mS). On some machines, this will cause a hang at boot time or
+ whenever the CPU becomes idle. (On machines with more than one CPU,
+ this option does nothing.)
Black display
CONFIG_APM_DISPLAY_BLANK
- Enable console blanking using the APM. Some laptops can use this to turn
- off the LCD backlight when the VC screen blanker blanks the screen. Note
- that this is only used by the VC screen blanker, and won't turn off the
- backlight when using X11.
+ Enable console blanking using the APM. Some laptops can use this to
+ turn off the LCD backlight when the VC screen blanker blanks the
+ screen. Note that this is only used by the VC screen blanker, and
+ won't turn off the backlight when using X11.
Sound card support
CONFIG_SOUND
ISDN subsystem
CONFIG_ISDN
- This allows you to use an ISDN-card for networking connections and as
- dialin/out device. The isdn-tty's have a builtin AT-compatible modem
- emulator. Network devices support autodial, channel-bundling, callback
- and caller-authentication without having a daemon running. A reduced T.70
- protocol is supported with tty's suitable for german BTX. Currently Cards
- by Teles and compatibles and ICN are supported. On D-Channel, the protocols
- EDSS1 and 1TR6 are supported. See Documentation/isdn/README for more
- information.
+ This allows you to use an ISDN-card for networking connections and
+ as dialin/out device. The isdn-tty's have a built in AT-compatible
+ modem emulator. Network devices support autodial, channel-bundling,
+ callback and caller-authentication without having a daemon
+ running. A reduced T.70 protocol is supported with tty's suitable
+ for German BTX. Currently Cards by Teles and compatibles and ICN are
+ supported. On D-Channel, the protocols EDSS1 and 1TR6 are
+ supported. See Documentation/isdn/README for more information.
Support synchronous PPP
CONFIG_ISDN_PPP
- This enables synchronous PPP via ISDN. This protocol is used by Cisco
- or Sun for example. You will need a special version of pppd (called ipppd)
- for using this feature. See Documentation/isdn/README.syncppp for more
- information.
+ This enables synchronous PPP via ISDN. This protocol is used by
+ Cisco or Sun for example. You will need a special version of pppd
+ (called ipppd) for using this feature. See
+ Documentation/isdn/README.syncppp for more information.
-Sypport generic MP (RFC 1717)
+Support generic MP (RFC 1717)
CONFIG_ISDN_MPP
- With synchronous PPP enabled, it is possible to increase throughput by
- bundling several ISDN-connections, using this protocol. See
+ With synchronous PPP enabled, it is possible to increase throughput
+ by bundling several ISDN-connections, using this protocol. See
Documentation/isdn/README.syncppp for more information.
Use VJ-compression with synchronous PPP
CONFIG_ISDN_PPP_VJ
- This enables Van Jacobson headercompression for synchronous PPP.
+ This enables Van Jacobson header compression for synchronous PPP.
ICN B1 and B2 support
CONFIG_ISDN_DRV_ICN
- This enables support for two kinds of ISDN-cards made by a german company
- called ICN. 1B is the standard version for a single ISDN line with two
- B-channels, 2B supports two ISDN lines. For running this card, additional
- firmware is necessary, which has to be downloaded into the card using
- a utility which is distributed separately.
- See Documentation/isdn/README and README.icn for more information.
+ This enables support for two kinds of ISDN-cards made by a German
+ company called ICN. 1B is the standard version for a single ISDN
+ line with two B-channels, 2B supports two ISDN lines. For running
+ this card, additional firmware is necessary, which has to be
+ downloaded into the card using a utility which is distributed
+ separately. See Documentation/isdn/README and README.icn for more
+ information.
Teles, NICCY1016PC, Creatix support
CONFIG_ISDN_DRV_TELES
- This enables support for the Teles ISDN-cards S0-16.0, S0-16.3, S0-8 and
- many compatibles. By default, the driver is configured to support
- a 16.0-type using EDSS1-protocol. See Documentation/isdn/README
- on how to configure it using 16.3, a different D-channel protocol, or
- non-standard irq/port/shmem settings.
+ This enables support for the Teles ISDN-cards S0-16.0, S0-16.3, S0-8
+ and many compatibles. By default, the driver is configured to
+ support a 16.0-type using EDSS1-protocol. See
+ Documentation/isdn/README on how to configure it using 16.3, a
+ different D-channel protocol, or non-standard irq/port/shmem
+ settings.
# need an empty line after last entry, for sed script in Configure.
# LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI
# LocalWords: QD qd UMC umc ALI ali lena fnet fr homepage azstarnet axplinux
# LocalWords: Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC
-# LocalWords: AlphaPC uwaterloo cpbeaure mca AOUT OUTput PPro sipx gwdg
+# LocalWords: AlphaPC uwaterloo cpbeaure mca AOUT OUTput PPro sipx gwdg lo nwe
# LocalWords: Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT
-# LocalWords: OPTi isp irq noisp VFAT vfat NTFS
+# LocalWords: OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP
+# LocalWords: NOWAYOUT behaviour dialin isdn callback BTX Teles ICN EDSS Cisco
+# LocalWords: ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem
%
\title{{\bf Linux Allocated Devices}}
\author{Maintained by H. Peter Anvin $<$hpa@storm.net$>$}
-\date{Last revised: February 17, 1996}
+\date{Last revised: February 24, 1996}
\maketitle
%
\noindent
\major{ 5}{}{char }{Alternate TTY devices}
\major{ 6}{}{char }{Parallel printer devices}
\major{ 7}{}{char }{Virtual console access devices}
+\major{ }{}{block}{Loopback devices}
\major{ 8}{}{block}{SCSI disk devices}
\major{ 9}{}{char }{SCSI tape devices}
\major{ }{}{block}{Metadisk (RAID) devices}
\major{37}{}{char }{IDE tape}
\major{ }{}{block}{Zorro II ramdisk}
\major{38}{}{char }{Myricom PCI Myrinet board}
-\major{39}{--40}{}{Unallocated}
-\major{41}{}{char}{Yet Another Micro Monitor}
+\major{39}{}{char }{ML-16P experimental I/O board}
+\major{40}{}{}{Unallocated}
+\major{41}{}{char }{Yet Another Micro Monitor}
\major{42}{}{}{Demo/sample use}
\major{43}{}{char }{isdn4linux virtual modem}
\major{44}{}{char }{isdn4linux virtual modem -- alternate devices}
\noindent
NOTE: These devices permit both read and write access.
+\major{ }{}{block}{Loopback devices}
+ \minor{0}{/dev/loop0}{First loopback device}
+ \minor{1}{/dev/loop1}{Second loopback device}
+ \minordots
+\end{devicelist}
+
+\noindent
+The loopback devices are used to mount filesystems not associated with
+block devices. The binding to the loopback devices is usually handled
+by mount(1).
+
\begin{devicelist}
\major{ 8}{}{block}{SCSI disk devices}
\minor{0}{/dev/sda}{First SCSI disk whole disk}
networking device.
\begin{devicelist}
-\major{39}{--40}{}{Unallocated}
+\major{39}{}{char }{ML-16P experimental I/O board}
+ \minor{0}{/dev/ml16pa-a0}{First card, first analog channel}
+ \minor{1}{/dev/ml16pa-a1}{First card, second analog channel}
+ \minordots
+ \minor{15}{/dev/ml16pa-a15}{First card, 16th analog channel}
+ \minor{16}{/dev/ml16pa-d}{First card, digital lines}
+ \minor{17}{/dev/ml16pa-c0}{First card, first counter/timer}
+ \minor{18}{/dev/ml16pa-c1}{First card, second counter/timer}
+ \minor{19}{/dev/ml16pa-c2}{First card, third counter/timer}
+ \minor{32}{/dev/ml16pb-a0}{Second card, first analog channel}
+ \minor{33}{/dev/ml16pb-a1}{Second card, second analog channel}
+ \minordots
+ \minor{47}{/dev/ml16pb-a15}{Second card, 16th analog channel}
+ \minor{48}{/dev/ml16pb-d}{Second card, digital lines}
+ \minor{49}{/dev/ml16pb-c0}{Second card, first counter/timer}
+ \minor{50}{/dev/ml16pb-c1}{Second card, second counter/timer}
+ \minor{51}{/dev/ml16pb-c2}{Second card, third counter/timer}
+ \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{40}{}{}{Unallocated}
\end{devicelist}
\begin{devicelist}
Maintained by H. Peter Anvin <hpa@storm.net>
- Last revised: February 17, 1996
+ Last revised: February 24, 1996
This list is the successor to Rick Miller's Linux Device List, which
he stopped maintaining when he got busy with other things in 1993. It
NOTE: These devices permit both read and write access.
+ block Loopback devices
+ 0 = /dev/loop0 First loopback device
+ 1 = /dev/loop1 Second loopback device
+ ...
+
+ The loopback devices are used to mount filesystems not
+ associated with block devices. The binding to the
+ loopback devices is usually handled by mount(1).
+
8 block SCSI disk devices
0 = /dev/sda First SCSI disk whole disk
16 = /dev/sdb Second SCSI disk whole disk
and "user level packet I/O." This board is also
accessible as a standard networking "eth" device.
- 39-40 UNALLOCATED
+ 39 char ML-16P experimental I/O board
+ 0 = /dev/ml16pa-a0 First card, first analog channel
+ 1 = /dev/ml16pa-a1 First card, second analog channel
+ ...
+ 15 = /dev/ml16pa-a15 First card, 16th analog channel
+ 16 = /dev/ml16pa-d First card, digital lines
+ 17 = /dev/ml16pa-c0 First card, first counter/timer
+ 18 = /dev/ml16pa-c1 First card, second counter/timer
+ 19 = /dev/ml16pa-c2 First card, third counter/timer
+ 32 = /dev/ml16pb-a0 Second card, first analog channel
+ 33 = /dev/ml16pb-a1 Second card, second analog channel
+ ...
+ 47 = /dev/ml16pb-a15 Second card, 16th analog channel
+ 48 = /dev/ml16pb-d Second card, digital lines
+ 49 = /dev/ml16pb-c0 Second card, first counter/timer
+ 50 = /dev/ml16pb-c1 Second card, second counter/timer
+ 51 = /dev/ml16pb-c2 Second card, third counter/timer
+
+ 40 UNALLOCATED
41 Yet Another Micro Monitor
0 = /dev/yamm Yet Another Micro Monitor
Remember, that according to the new strategy for accessing Low-level-drivers
from within isdn4linux you should also define a driver-id while doing
-insmod: Simply append id=<SomeString> to the insmod-commandline. This
+insmod: Simply append teles_id=<SomeString> to the insmod-commandline. This
string MUST NOT start with a digit or a small 'x'!
At this point you can run a 'cat /dev/isdnctrl0' and view debugging
Odd Fixes: It has a maintainer but they don't have time to do
much other than throw the odd patch in. See below..
Orphan: No current maintainer [but maybe you could take the
- role as you write your new driver].
+ role as you write your new code].
Obsolete: Ex code. Something tagged obsolete generally means
its been replaced by a better system and you should
be using that.
L: linux-ipx@vger.rutgers.edu [will change]
S: Maintained
+ISDN SUBSYSTEM
+P: Fritz Elfert
+M: fritz@wuemaus.franken.de
+L: isdn4linux@hub-wue.franken.de
+S: Maintained
+
NETROM NETWORK LAYER
P: Jon Naylor
M: jsn@cs.nott.ac.uk
VERSION = 1
PATCHLEVEL = 3
-SUBLEVEL = 69
+SUBLEVEL = 70
ARCH = i386
#
ALL_MOBJS = $(MX_OBJS) $(M_OBJS)
ifneq "$(strip $(ALL_MOBJS))" ""
-PDWN=$(shell /bin/sh $(TOPDIR)/scripts/pathdown.sh)
+PDWN=$(shell $(CONFIG_SHELL) $(TOPDIR)/scripts/pathdown.sh)
endif
modules: $(ALL_MOBJS) dummy
ifdef MOD_SUB_DIRS
EB66 CONFIG_ALPHA_EB66 \
EB66+ CONFIG_ALPHA_EB66P \
EB64+ CONFIG_ALPHA_EB64P \
+ EB164 CONFIG_ALPHA_EB164 \
Jensen CONFIG_ALPHA_JENSEN \
Noname CONFIG_ALPHA_NONAME \
Platform2000 CONFIG_ALPHA_P2K" Cabriolet
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_APECS y
fi
+if [ "$CONFIG_ALPHA_EB164" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_EV5 y
+ define_bool CONFIG_ALPHA_ALCOR y
+fi
# This needs to be defined for all EV4 and EV45 CPUs:
define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
bool 'Echo console messages on /dev/ttyS1' CONFIG_SERIAL_ECHO
#
CONFIG_NATIVE=y
# CONFIG_ALPHA_AVANTI is not set
-# CONFIG_ALPHA_JENSEN is not set
-# CONFIG_ALPHA_NONAME is not set
# CONFIG_ALPHA_CABRIOLET is not set
-# CONFIG_ALPHA_P2K is not set
# CONFIG_ALPHA_EB66 is not set
# CONFIG_ALPHA_EB66P is not set
-CONFIG_ALPHA_EB64P=y
-# CONFIG_ALPHA_SRM is not set
+# CONFIG_ALPHA_EB64P is not set
+CONFIG_ALPHA_EB164=y
+# CONFIG_ALPHA_JENSEN is not set
+# CONFIG_ALPHA_NONAME is not set
+# CONFIG_ALPHA_P2K is not set
CONFIG_PCI=y
-CONFIG_ALPHA_APECS=y
+CONFIG_ALPHA_EV5=y
+CONFIG_ALPHA_ALCOR=y
CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
# CONFIG_SERIAL_ECHO is not set
# CONFIG_TGA_CONSOLE is not set
# CONFIG_BINFMT_ELF is not set
#
-# Block devices
+# Floppy, IDE, and other block devices
#
CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_ST506=y
+# CONFIG_BLK_DEV_IDE is not set
#
# Please see drivers/block/README.ide for help/info on IDE drives
#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_TRITON is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_HD_ONLY is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_MD is not set
#
# Networking options
O_TARGET := kernel.o
O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- bios32.o ptrace.o time.o apecs.o lca.o ksyms.o
+ bios32.o ptrace.o time.o apecs.o lca.o alcor.o ksyms.o
all: kernel.o head.o
--- /dev/null
+/*
+ * Code common to all ALCOR chips.
+ *
+ * Written by David A Rusling (david.rusling@reo.mts.dec.com).
+ * December 1995.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/hwrpb.h>
+#include <asm/ptrace.h>
+#include <asm/mmu_context.h>
+
+extern struct hwrpb_struct *hwrpb;
+extern asmlinkage void wrmces(unsigned long mces);
+extern int alpha_sys_type;
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef CONFIG_ALPHA_ALCOR
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define vulp volatile unsigned long *
+#define vuip volatile unsigned int *
+
+static volatile unsigned int ALCOR_mcheck_expected = 0;
+static volatile unsigned int ALCOR_mcheck_taken = 0;
+static unsigned long ALCOR_jd, ALCOR_jd1, ALCOR_jd2;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the ALCOR_HAXR2 register
+ * accordingly. It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Type 0:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:11 Device select bit.
+ * 10:8 Function number
+ * 7:2 Register number
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., scsi and ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+
+ DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ if (bus == 0) {
+ int device = device_fn >> 3;
+
+ /* type 0 configuration cycle: */
+
+ if (device > 20) {
+ DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", device));
+ return -1;
+ }
+
+ *type1 = 0;
+ addr = (device_fn << 8) | (where);
+ } else {
+ /* type 1 configuration cycle: */
+ *type1 = 1;
+ addr = (bus << 16) | (device_fn << 8) | (where);
+ }
+ *pci_addr = addr;
+ DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+
+static unsigned int conf_read(unsigned long addr, unsigned char type1)
+{
+ unsigned long flags;
+ unsigned int stat0, value;
+ unsigned int cia_cfg = 0; /* to keep gcc quiet */
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+ /* reset status register to avoid losing errors: */
+ stat0 = *((volatile unsigned int *)ALCOR_IOC_CIA_ERR);
+ *((volatile unsigned int *)ALCOR_IOC_CIA_ERR) = stat0;
+ mb();
+ DBG(("conf_read: ALCOR CIA ERR was 0x%x\n", stat0));
+ /* if Type1 access, must set CIA CFG */
+ if (type1) {
+ cia_cfg = *((unsigned int *)ALCOR_IOC_CFG);
+ mb();
+ *((unsigned int *)ALCOR_IOC_CFG) = cia_cfg | 1;
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ draina();
+ ALCOR_mcheck_expected = 1;
+ ALCOR_mcheck_taken = 0;
+ mb();
+ /* access configuration space: */
+ value = *((volatile unsigned int *)addr);
+ mb();
+ mb();
+ if (ALCOR_mcheck_taken) {
+ ALCOR_mcheck_taken = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ ALCOR_mcheck_expected = 0;
+ mb();
+ /*
+ * david.rusling@reo.mts.dec.com. This code is needed for the
+ * EB64+ as it does not generate a machine check (why I don't
+ * know). When we build kernels for one particular platform
+ * then we can make this conditional on the type.
+ */
+#if 1
+ draina();
+
+ /* now look for any errors */
+ stat0 = *((unsigned int *)ALCOR_IOC_CIA_ERR);
+ DBG(("conf_read: ALCOR CIA ERR after read 0x%x\n", stat0));
+ if (stat0 & 0x8280U) { /* is any error bit set? */
+ /* if not NDEV, print status */
+ if (!(stat0 & 0x0080)) {
+ printk("ALCOR.c:conf_read: got stat0=%x\n", stat0);
+ }
+
+ /* reset error status: */
+ *((volatile unsigned long *)ALCOR_IOC_CIA_ERR) = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+ value = 0xffffffff;
+ }
+#endif
+
+ /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ if (type1) {
+ *((unsigned int *)ALCOR_IOC_CFG) = cia_cfg & ~1;
+ mb();
+ }
+
+ DBG(("conf_read(): finished\n"));
+
+ restore_flags(flags);
+ return value;
+}
+
+
+static void conf_write(unsigned long addr, unsigned int value, unsigned char type1)
+{
+ unsigned long flags;
+ unsigned int stat0;
+ unsigned int cia_cfg = 0; /* to keep gcc quiet */
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ /* reset status register to avoid losing errors: */
+ stat0 = *((volatile unsigned int *)ALCOR_IOC_CIA_ERR);
+ *((volatile unsigned int *)ALCOR_IOC_CIA_ERR) = stat0;
+ mb();
+ DBG(("conf_write: ALCOR CIA ERR was 0x%x\n", stat0));
+ /* if Type1 access, must set CIA CFG */
+ if (type1) {
+ cia_cfg = *((unsigned int *)ALCOR_IOC_CFG);
+ mb();
+ *((unsigned int *)ALCOR_IOC_CFG) = cia_cfg | 1;
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ draina();
+ ALCOR_mcheck_expected = 1;
+ mb();
+ /* access configuration space: */
+ *((volatile unsigned int *)addr) = value;
+ mb();
+ mb();
+ ALCOR_mcheck_expected = 0;
+ mb();
+ /*
+ * david.rusling@reo.mts.dec.com. This code is needed for the
+ * EB64+ as it does not generate a machine check (why I don't
+ * know). When we build kernels for one particular platform
+ * then we can make this conditional on the type.
+ */
+#if 1
+ draina();
+
+ /* now look for any errors */
+ stat0 = *((unsigned int *)ALCOR_IOC_CIA_ERR);
+ DBG(("conf_write: ALCOR CIA ERR after write 0x%x\n", stat0));
+ if (stat0 & 0x8280U) { /* is any error bit set? */
+ /* if not NDEV, print status */
+ if (!(stat0 & 0x0080)) {
+ printk("ALCOR.c:conf_read: got stat0=%x\n", stat0);
+ }
+
+ /* reset error status: */
+ *((volatile unsigned long *)ALCOR_IOC_CIA_ERR) = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+ value = 0xffffffff;
+ }
+#endif
+
+ /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ if (type1) {
+ *((unsigned int *)ALCOR_IOC_CFG) = cia_cfg & ~1;
+ mb();
+ }
+
+ DBG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+
+int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char *value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ addr |= (pci_addr << 5) + 0x00;
+
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short *value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+
+ if (where & 0x1) {
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ addr |= (pci_addr << 5) + 0x08;
+
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int *value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+ if (where & 0x3) {
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int value)
+{
+ unsigned long addr = ALCOR_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+unsigned long alcor_init(unsigned long mem_start, unsigned long mem_end)
+{
+ unsigned int cia_err ;
+
+ /*
+ * Set up error reporting.
+ */
+ cia_err = *(vuip)ALCOR_IOC_CIA_ERR ;
+ cia_err |= (0x1 << 7) ; /* master abort */
+ *(vuip)ALCOR_IOC_CIA_ERR = cia_err ;
+ mb() ;
+
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the future, we may
+ * want to use them to do scatter/gather DMA. Window 0
+ * goes at 1 GB and is 1 GB large.
+ */
+
+ *(vuip)ALCOR_IOC_PCI_W0_BASE = 1U | (ALCOR_DMA_WIN_BASE & 0xfff00000U);
+ *(vuip)ALCOR_IOC_PCI_W0_MASK = (ALCOR_DMA_WIN_SIZE - 1) & 0xfff00000U;
+ *(vuip)ALCOR_IOC_PCI_T0_BASE = 0;
+
+ *(vuip)ALCOR_IOC_PCI_W1_BASE = 0x0 ;
+ *(vuip)ALCOR_IOC_PCI_W2_BASE = 0x0 ;
+ *(vuip)ALCOR_IOC_PCI_W3_BASE = 0x0 ;
+
+ /*
+ * check ASN in HWRPB for validity, report if bad
+ */
+ if (hwrpb->max_asn != MAX_ASN) {
+ printk("alcor_init: max ASN from HWRPB is bad (0x%lx)\n",
+ hwrpb->max_asn);
+ hwrpb->max_asn = MAX_ASN;
+ }
+
+ return mem_start;
+}
+
+int ALCOR_pci_clr_err(void)
+{
+ ALCOR_jd = *((unsigned int *)ALCOR_IOC_CIA_ERR);
+ DBG(("ALCOR_pci_clr_err: ALCOR CIA ERR after read 0x%x\n", ALCOR_jd));
+ *((unsigned long *)ALCOR_IOC_CIA_ERR) = 0x0080;
+ mb();
+ return 0;
+}
+
+void alcor_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#if 1
+ printk("ALCOR machine check\n") ;
+#else
+ struct el_common *mchk_header;
+ struct el_ALCOR_sysdata_mcheck *mchk_sysdata;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata =
+ (struct el_ALCOR_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
+
+ DBG(("ALCOR_machine_check: vector=0x%lx la_ptr=0x%lx\n", vector, la_ptr));
+ DBG((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset, mchk_header->sys_offset));
+ DBG(("ALCOR_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ ALCOR_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear));
+#ifdef DEBUG
+ {
+ unsigned long *ptr;
+ int i;
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+ }
+#endif /* DEBUG */
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ if (ALCOR_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) {
+ ALCOR_mcheck_expected = 0;
+ ALCOR_mcheck_taken = 1;
+ mb();
+ mb();
+ ALCOR_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ draina();
+ }
+#endif
+}
+
+#endif /* CONFIG_ALPHA_ALCOR */
*/
#define PCI_MODIFY 1
-
extern struct hwrpb_struct *hwrpb;
/*
* Go through all devices, fixing up irqs as we see fit:
*/
- level_bits = 0;
+ level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
for (dev = pci_devices; dev; dev = dev->next) {
dev->irq = 0;
if (dev->bus->number != 0) {
if (pirq < 0) {
continue;
}
+
/*
* if its a VGA, enable its BIOS ROM at C0000
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/malloc.h>
#include <linux/random.h>
#include <asm/system.h>
/*
* Initial irq handlers.
*/
-struct irqaction {
- void (*handler)(int, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
-};
-
-static struct irqaction irq_action[NR_IRQS];
+static struct irqaction *irq_action[NR_IRQS];
int get_irq_list(char *buf)
{
int i, len = 0;
- struct irqaction * action = irq_action;
+ struct irqaction * action;
- for (i = 0 ; i < NR_IRQS ; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%2d: %8d %c %s\n",
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = *(i + irq_action);
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
return len;
}
}
}
-int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char * devname)
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
{
- struct irqaction * action;
+ struct irqaction *action, *tmp = NULL;
unsigned long flags;
if (irq >= NR_IRQS)
/* don't accept requests for irq #0 */
if (!irq)
return -EINVAL;
- action = irq + irq_action;
- if (action->handler)
- return -EBUSY;
if (!handler)
- return -EINVAL;
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
+ return -EBUSY;
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
save_flags(flags);
cli();
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
- enable_irq(irq);
- if (irq >= 8 && irq < 16) {
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
+ enable_irq(irq);
+ if (irq >= 8 && irq < 16) {
enable_irq(2); /* ensure cascade is enabled too */
+ }
}
+
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq)
+void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+ struct irqaction * tmp = NULL;
unsigned long flags;
if (irq >= NR_IRQS) {
printk("Trying to free free IRQ%d\n", irq);
return;
}
+ if (dev_id) {
+ for (; action; action = action->next) {
+ if (action->dev_id == dev_id) break;
+ tmp = action;
+ }
+ if (!action) {
+ printk("Trying to free free shared IRQ%d\n",irq);
+ return;
+ }
+ } else if (action->flags & SA_SHIRQ) {
+ printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+ return;
+ }
save_flags(flags);
cli();
- mask_irq(irq);
- action->handler = NULL;
- action->flags = 0;
- action->mask = 0;
- action->name = NULL;
+ if (action && tmp) {
+ tmp->next = action->next;
+ } else {
+ *(irq + irq_action) = action->next;
+ }
+ kfree_s(action, sizeof(struct irqaction));
+
+ if (!(*(irq + irq_action))) {
+ mask_irq(irq);
+ }
+
restore_flags(flags);
}
printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
}
-static void unexpected_irq(int irq, struct pt_regs * regs)
+static void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
{
+ struct irqaction *action;
int i;
printk("IO device interrupt, irq = %d\n", irq);
printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
printk("Expecting: ");
for (i = 0; i < 16; i++)
- if (irq_action[i].handler)
- printk("[%s:%d] ", irq_action[i].name, i);
+ if ((action = *(i + irq_action)))
+ while (action->handler) {
+ printk("[%s:%d] ", action->name, i);
+ action = action->next;
+ }
printk("\n");
#if defined(CONFIG_ALPHA_JENSEN)
printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
#endif
}
-static inline void handle_irq(int irq, struct pt_regs * regs)
+static inline void handle_irq(int irq, void *dev_id, struct pt_regs * regs)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
kstat.interrupts[irq]++;
- if (!action->handler) {
- unexpected_irq(irq, regs);
- return;
+ if (!action) {
+ unexpected_irq(irq, action->dev_id, regs);
+ return;
+ }
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
}
- action->handler(irq, regs);
}
static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
}
kstat.interrupts[irq]++;
- action = irq_action + irq;
+ action = *(irq_action + irq);
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
/* quick interrupts get executed with no extra overhead */
if (action->flags & SA_INTERRUPT) {
- action->handler(irq, regs);
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
ack_irq(ack);
return;
}
*/
mask_irq(ack);
ack_irq(ack);
- if (!action->handler)
+ if (!action)
return;
- action->handler(irq, regs);
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
unmask_irq(ack);
}
# define IACK_SC APECS_IACK_SC
#elif defined(CONFIG_ALPHA_LCA)
# define IACK_SC LCA_IACK_SC
+#elif defined(CONFIG_ALPHA_ALCOR)
+# define IACK_SC ALCOR_IACK_SC
#else
/*
* This is bogus but necessary to get it to compile
#endif
int j;
+#if 1
/*
* Generate a PCI interrupt acknowledge cycle. The PIC will
* respond with the interrupt vector of the highest priority
}
}
device_interrupt(j, j, regs);
-#if 0
+#else
unsigned long pic;
/*
/* read the interrupt summary registers */
pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
+#if 0
+ printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
+#endif
+
/*
* Now for every possible bit set, work through them and call
* the appropriate interrupt handler.
static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
int irq, ack;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
ack = irq = (vector - 0x800) >> 4;
#endif /* CONFIG_ALPHA_JENSEN */
device_interrupt(irq, ack, regs);
+
+ restore_flags(flags) ;
}
#if NR_IRQS > 64
*/
unsigned long probe_irq_on(void)
{
+ struct irqaction * action;
unsigned long irqs = 0, irqmask;
unsigned long delay;
unsigned int i;
for (i = NR_IRQS - 1; i > 0; i--) {
- if (!irq_action[i].handler) {
+ action = *(i + irq_action);
+ if (!action->handler) {
enable_irq(i);
irqs |= (1 << i);
}
extern void apecs_machine_check(unsigned long vector, unsigned long la,
struct pt_regs * regs);
apecs_machine_check(vector, la, regs);
+#elif defined(CONFIG_ALPHA_ALCOR)
+ extern void alcor_machine_check(unsigned long vector, unsigned long la,
+ struct pt_regs * regs);
+ alcor_machine_check(vector, la, regs);
#else
printk("Machine check\n");
#endif
*memory_start_p = lca_init(*memory_start_p, *memory_end_p);
#elif defined(CONFIG_ALPHA_APECS)
*memory_start_p = apecs_init(*memory_start_p, *memory_end_p);
+#elif defined(CONFIG_ALPHA_ALCOR)
+ *memory_start_p = alcor_init(*memory_start_p, *memory_end_p);
#endif
}
! ld86 requires an entry symbol. This may as well be the usual one.
.globl _main
_main:
- nop
- jmp over_magic
- .byte 0xF0
-over_magic:
#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
int 3
#endif
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/malloc.h>
#include <linux/random.h>
#include <asm/system.h>
#include <asm/smp.h>
#define CR0_NE 32
+#define TIMER_IRQ 0 /* Keep this in sync with time.c */
static unsigned char cache_21 = 0xff;
static unsigned char cache_A1 = 0xff;
/*
* Initial irq handlers.
*/
-struct irqaction {
- void (*handler)(int, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
-};
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction irq_action[16] = {
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+static struct irqaction *irq_action[16] = {
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
int get_irq_list(char *buf)
{
int i, len = 0;
- struct irqaction * action = irq_action;
+ struct irqaction * action;
- for (i = 0 ; i < 16 ; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%3d: %8d %c %s\n",
+ for (i = 0 ; i < 16 ; i++) {
+ action = *(i + irq_action);
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
/*
* Linus - should you add NMI counts here ?????
int get_smp_prof_list(char *buf) {
int i,j, len = 0;
- struct irqaction * action = irq_action;
+ struct irqaction * action;
unsigned long sum_spins = 0;
unsigned long sum_spins_syscall = 0;
unsigned long sum_spins_sys_idle = 0;
for (i=0;i<smp_num_cpus;i++)
len += sprintf(buf+len," P%1d ",i);
len += sprintf(buf+len,"\n");
- for (i = 0 ; i < NR_IRQS ; i++, action++) {
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = *(i + irq_action);
if (!action->handler)
continue;
len += sprintf(buf+len, "%3d: %10d ",
len += sprintf(buf+len, "%c %s\n",
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
}
len+=sprintf(buf+len, "LCK: %10lu",
sum_spins);
*/
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+
#ifdef __SMP__
if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
#ifdef __SMP_PROF__
int_count[smp_processor_id()][irq]++;
#endif
- if (action->flags & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- action->handler(irq, regs);
+ while (action) {
+ if (action->flags & SA_SAMPLE_RANDOM) {
+ add_interrupt_randomness(irq);
+ }
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
}
/*
*/
asmlinkage void do_fast_IRQ(int irq)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
#ifdef __SMP__
/* IRQ 13 is allowed - thats an invalidate */
if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
#ifdef __SMP_PROF__
int_count[smp_processor_id()][irq]++;
#endif
- if (action->flags & SA_SAMPLE_RANDOM)
+ while (action) {
+ if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
- action->handler(irq, NULL);
+ action->handler(irq, action->dev_id, NULL);
+ action = action->next;
+ }
}
#define SA_PROBE SA_ONESHOT
-int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char * devname)
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
{
- struct irqaction * action;
+ struct irqaction * action, *tmp = NULL;
unsigned long flags;
if (irq > 15)
- return -EINVAL;
- action = irq + irq_action;
- if (action->handler)
- return -EBUSY;
+ return -EINVAL;
if (!handler)
- return -EINVAL;
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
+ return -EBUSY;
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
if (irqflags & SA_SAMPLE_RANDOM)
rand_initialize_irq(irq);
save_flags(flags);
cli();
+ if (irq == 2)
+ action = &cascade_irq;
+ else if (irq == 13)
+ action = &math_irq;
+ else if (irq == TIMER_IRQ)
+ action = &timer_irq;
+ else
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
- if (!(action->flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
+ if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */
if (action->flags & SA_INTERRUPT)
- set_intr_gate(0x20+irq,fast_interrupt[irq]);
+ set_intr_gate(0x20+irq,fast_interrupt[irq]);
else
- set_intr_gate(0x20+irq,interrupt[irq]);
- }
- if (irq < 8) {
+ set_intr_gate(0x20+irq,interrupt[irq]);
+ }
+ if (irq < 8) {
cache_21 &= ~(1<<irq);
outb(cache_21,0x21);
- } else {
+ } else {
cache_21 &= ~(1<<2);
cache_A1 &= ~(1<<(irq-8));
outb(cache_21,0x21);
outb(cache_A1,0xA1);
+ }
}
+
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq)
+void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+ struct irqaction * tmp = NULL;
unsigned long flags;
if (irq > 15) {
printk("Trying to free free IRQ%d\n",irq);
return;
}
+ if (dev_id) {
+ for (; action; action = action->next) {
+ if (action->dev_id == dev_id) break;
+ tmp = action;
+ }
+ if (!action) {
+ printk("Trying to free free shared IRQ%d\n",irq);
+ return;
+ }
+ } else if (action->flags & SA_SHIRQ) {
+ printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+ return;
+ }
save_flags(flags);
cli();
- if (irq < 8) {
+ if (action && tmp) {
+ tmp->next = action->next;
+ } else {
+ *(irq + irq_action) = action->next;
+ }
+
+ if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
+ memset(action, 0, sizeof(struct irqaction));
+ else
+ kfree_s(action, sizeof(struct irqaction));
+
+ if (!(*(irq + irq_action))) {
+ if (irq < 8) {
cache_21 |= 1 << irq;
outb(cache_21,0x21);
- } else {
+ } else {
cache_A1 |= 1 << (irq-8);
outb(cache_A1,0xA1);
+ }
+ set_intr_gate(0x20+irq,bad_interrupt[irq]);
}
- set_intr_gate(0x20+irq,bad_interrupt[irq]);
- action->handler = NULL;
- action->flags = 0;
- action->mask = 0;
- action->name = NULL;
+
restore_flags(flags);
}
*/
-static void math_error_irq(int cpl, struct pt_regs *regs)
+static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
{
outb(0,0xF0);
if (ignore_irq13 || !hard_math)
#endif
-static void no_action(int cpl, struct pt_regs * regs) { }
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
unsigned long probe_irq_on (void)
{
/* first, snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!request_irq(i, no_action, SA_PROBE, "probe")) {
+ if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
enable_irq(i);
irqs |= (1 << i);
}
for (i = 15; i > 0; i--) {
if (irqs & (1 << i) & irqmask) {
irqs ^= (1 << i);
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i)) {
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
#ifdef __SMP__
set_intr_gate(0x20+i, interrupt[i]); /* IRQ '16' - IPI for rescheduling */
#endif
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
+ if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
printk("Unable to get IRQ2 for cascade.\n");
#ifndef __SMP__
- if (request_irq(13,math_error_irq, 0, "math error"))
+ if (request_irq(13, math_error_irq, 0, "math error", NULL))
printk("Unable to get IRQ13 for math-error handler.\n");
#else
- if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI"))
+ if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI", NULL))
printk("Unable to get IRQ13 for IPI.\n");
#endif
request_region(0x20,0x20,"pic1");
* Much of the core SMP work is based on previous work by Thomas Radke, to
* whom a great many thanks are extended.
*
+ * Thanks to Intel for testing against several Pentium and Pentium Pro
+ * MP machines.
*
* This code is released under the GNU public license version 2 or
* later.
#include <asm/pgtable.h>
#include <asm/smp.h>
-static int smp_found_config=0; /* Have we found an SMP box */
+int smp_found_config=0; /* Have we found an SMP box */
unsigned long cpu_present_map = 0; /* Bitmask of existing CPU's */
int smp_num_cpus; /* Total count of live CPU's */
int smp_threads_ready=0; /* Set when the idlers are all forked */
-volatile unsigned long cpu_number_map[NR_CPUS]; /* which CPU maps to which logical number */
+volatile int cpu_number_map[NR_CPUS]; /* which CPU maps to which logical number */
volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; /* We always use 0 the rest is ready for parallel delivery */
volatile unsigned long smp_invalidate_needed; /* Used for the invalidate map thats also checked in the spinlock */
struct cpuinfo_x86 cpu_data[NR_CPUS]; /* Per cpu bogomips and other parameters */
unsigned char boot_cpu_id = 0; /* Processor that is doing the boot up */
static unsigned char *kstack_base,*kstack_end; /* Kernel stack list pointers */
static int smp_activated = 0; /* Tripped once we need to start cross invalidating */
+int apic_version[NR_CPUS]; /* APIC version number */
static volatile int smp_commenced=0; /* Tripped when we start scheduling */
unsigned long apic_addr=0xFEE00000; /* Address of APIC (defaults to 0xFEE00000) */
unsigned long nlong = 0; /* dummy used for apic_reg address + 0x20 */
"Unknown","Unknown",
"80486DX/4"
};
+ if(family==0x6)
+ return("Pentium(tm) Pro");
if(family==0x5)
return("Pentium(tm)");
if(family==0x0F && model==0x0F)
if(m->mpc_apicid>NR_CPUS)
printk("Processor #%d unused. (Max %d processors).\n",m->mpc_apicid, NR_CPUS);
else
+ {
cpu_present_map|=(1<<m->mpc_apicid);
+ apic_version[m->mpc_apicid]=m->mpc_apicver;
+ }
}
mpt+=sizeof(*m);
count+=sizeof(*m);
else
cpu_present_map=3;
printk("Processors: %d\n", num_processors);
+ /*
+ * Only use the first one found.
+ */
+ return;
}
}
bp+=4;
void smp_boot_cpus(void)
{
- int i=0;
+ int i,j;
int cpucount=0;
+ unsigned long cfg;
void *stack;
extern unsigned long init_user_stack[];
+ /*
+ * Initialize the logical to physical cpu number mapping
+ */
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_number_map[i] = -1;
+
+ /*
+ * Setup boot CPU information
+ */
+
+ kernel_stacks[boot_cpu_id]=(void *)init_user_stack; /* Set up for boot processor first */
+
+ smp_store_cpu_info(boot_cpu_id); /* Final full version of the data */
+
+ cpu_present_map |= (1 << smp_processor_id());
+ cpu_number_map[boot_cpu_id] = 0;
+ active_kernel_processor=boot_cpu_id;
+
+ /*
+ * If we don't conform to the Intel MPS standard, get out
+ * of here now!
+ */
+
+ if (!smp_found_config)
+ return;
+
/*
* Map the local APIC into kernel space
*/
- /* Mapping on non-Intel conforming platforms is a bad move. */
- if (1<cpu_present_map)
- apic_reg = vremap(0xFEE00000,4096);
-
+ apic_reg = vremap(0xFEE00000,4096);
if(apic_reg == NULL)
panic("Unable to map local apic.\n");
{
int reg;
+ /*
+ * This is to verify that we're looking at
+ * a real local APIC. Check these against
+ * your board if the CPUs aren't getting
+ * started for no apparent reason.
+ */
+
reg = apic_read(APIC_VERSION);
- printk("Getting VERSION: %x\n", reg);
+ SMP_PRINTK(("Getting VERSION: %x\n", reg));
apic_write(APIC_VERSION, 0);
reg = apic_read(APIC_VERSION);
- printk("Getting VERSION: %x\n", reg);
+ SMP_PRINTK(("Getting VERSION: %x\n", reg));
+
+ /*
+ * The two version reads above should print the same
+ * NON-ZERO!!! numbers. If the second one is zero,
+ * there is a problem with the APIC write/read
+ * definitions.
+ *
+ * The next two are just to see if we have sane values.
+ * They're only really relevant if we're in Virtual Wire
+ * compatibility mode, but most boxes are anymore.
+ */
+
reg = apic_read(APIC_LVT0);
- printk("Getting LVT0: %x\n", reg);
+ SMP_PRINTK(("Getting LVT0: %x\n", reg));
reg = apic_read(APIC_LVT1);
- printk("Getting LVT1: %x\n", reg);
+ SMP_PRINTK(("Getting LVT1: %x\n", reg));
}
#endif
/*
- * Now scan the cpu present map and fire up anything we find.
+ * Enable the local APIC
*/
-
- kernel_stacks[boot_cpu_id]=(void *)init_user_stack; /* Set up for boot processor first */
-
- smp_store_cpu_info(boot_cpu_id); /* Final full version of the data */
-
- active_kernel_processor=boot_cpu_id;
+
+ cfg=apic_read(APIC_SPIV);
+ cfg|=(1<<8); /* Enable APIC */
+ apic_write(APIC_SPIV,cfg);
+ udelay(10);
+
+ /*
+ * Now scan the cpu present map and fire up the other CPUs.
+ */
+
SMP_PRINTK(("CPU map: %lx\n", cpu_present_map));
for(i=0;i<NR_CPUS;i++)
{
- if((cpu_present_map&(1<<i)) && i!=boot_cpu_id) /* Rebooting yourself is a bad move */
+ /*
+ * Don't even attempt to start the boot CPU!
+ */
+ if (i == boot_cpu_id)
+ continue;
+
+ if (cpu_present_map & (1 << i))
{
- unsigned long cfg, send_status, accept_status;
- int timeout;
+ unsigned long send_status, accept_status;
+ int timeout, num_starts;
/*
* We need a kernel stack for each processor.
install_trampoline(stack);
printk("Booting processor %d stack %p: ",i,stack); /* So we set whats up */
-
- /*
- * Enable the local APIC
- */
-
- cfg=apic_read(APIC_SPIV);
- cfg|=(1<<8); /* Enable APIC */
- apic_write(APIC_SPIV,cfg);
-
- /*
+
+ /*
* This gunge runs the startup process for
* the targeted processor.
*/
SMP_PRINTK(("Setting warm reset code and vector.\n"));
/*
- * Needed to boot a 486 board.
+ * Install a writable page 0 entry.
*/
CMOS_WRITE(0xa, 0xf);
pg0[0]=7;
+ local_invalidate();
*((volatile unsigned short *) 0x467) = ((unsigned long)stack)>>4;
*((volatile unsigned short *) 0x469) = 0;
+
+ /*
+ * Protect it again
+ */
+
pg0[0]= pte_val(mk_pte(0, PAGE_READONLY));
+ local_invalidate();
/*
- * Clean up the errors
+ * Be paranoid about clearing APIC errors.
*/
apic_write(APIC_ESR, 0);
* Status is now clean
*/
- send_status = 0;
+ send_status = 0;
accept_status = 0;
+ /*
+ * Starting actual IPI sequence...
+ */
+
SMP_PRINTK(("Asserting INIT.\n"));
/*
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
cfg=apic_read(APIC_ICR);
cfg&=~0xCDFFF; /* Clear bits */
- cfg|=0x0000c500; /* Urgh.. fix for constants */
+ cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
+ | APIC_DEST_ASSERT | APIC_DEST_DM_INIT);
apic_write(APIC_ICR, cfg); /* Send IPI */
- timeout = 0;
- do {
- udelay(1000);
- if ((send_status = (!(apic_read(APIC_ICR) & 0x00001000))))
- break;
- } while (timeout++ < 1000);
-
-#ifdef EEK2
- if (send_status) {
- apic_write(APIC_ESR, 0);
- accept_status = (apic_read(APIC_ESR) & 0xEF);
- }
-#endif
+ udelay(200);
+ SMP_PRINTK(("Deasserting INIT.\n"));
+ cfg=apic_read(APIC_ICR2);
+ cfg&=0x00FFFFFF;
+ apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
+ cfg=apic_read(APIC_ICR);
+ cfg&=~0xCDFFF; /* Clear bits */
+ cfg |= (APIC_DEST_FIELD | APIC_DEST_LEVELTRIG
+ | APIC_DEST_DM_INIT);
+ apic_write(APIC_ICR, cfg); /* Send IPI */
+
/*
- * And off again
+ * Should we send STARTUP IPIs ?
+ *
+ * Determine this based on the APIC version.
+ * If we don't have an integrated APIC, don't
+ * send the STARTUP IPIs.
*/
-
- if (send_status && !accept_status)
- {
- SMP_PRINTK(("Deasserting INIT.\n"));
-
- cfg=apic_read(APIC_ICR2);
- cfg&=0x00FFFFFF;
- apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
- cfg=apic_read(APIC_ICR);
- cfg&=~0xCDFFF; /* Clear bits */
- cfg|=0x00008500;
- apic_write(APIC_ICR, cfg); /* Send IPI */
-
- timeout = 0;
- do {
- udelay(1000);
- if ((send_status = !(apic_read(APIC_ICR) & 0x00001000) ))
- break;
- } while (timeout++ < 1000);
- if (send_status) {
- udelay(1000000);
- apic_write(APIC_ESR, 0);
- accept_status = (apic_read(APIC_ESR) & 0xEF);
- }
- }
+ if ( apic_version[i] & 0xF0 )
+ num_starts = 2;
+ else
+ num_starts = 0;
/*
- * We currently assume an integrated
- * APIC only, so STARTUP IPIs must be
- * sent as well.
+ * Run STARTUP IPI loop.
*/
- if (send_status && !accept_status)
+ for (j = 0; !(send_status || accept_status)
+ && (j < num_starts) ; j++)
{
- SMP_PRINTK(("Sending first STARTUP.\n"));
-
- /*
- * First STARTUP IPI
- */
-
- cfg=apic_read(APIC_ICR2);
- cfg&=0x00FFFFFF;
- apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
- cfg=apic_read(APIC_ICR);
- cfg&=~0xCDFFF ; /* Clear bits */
- cfg|=APIC_DEST_FIELD|APIC_DEST_DM_STARTUP|(((unsigned long)stack)>>12); /* Boot on the stack */
- apic_write(APIC_ICR, cfg); /* Kick the second */
+ SMP_PRINTK(("Sending STARTUP #%d.\n",j));
- timeout = 0;
- do {
- udelay(1000);
- if ((send_status = !(apic_read(APIC_ICR) & 0x00001000)) )
- break;
- } while (timeout++ < 1000);
-
- if (send_status) {
- udelay(1000000);
- apic_write(APIC_ESR, 0);
- accept_status = (apic_read(APIC_ESR) & 0xEF);
- }
- }
-
- if (send_status && !accept_status)
- {
- SMP_PRINTK(("Sending second STARTUP.\n"));
+ apic_write(APIC_ESR, 0);
/*
- * Second STARTUP IPI
+ * STARTUP IPI
*/
cfg=apic_read(APIC_ICR2);
cfg&=0x00FFFFFF;
apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); /* Target chip */
cfg=apic_read(APIC_ICR);
- cfg&=~0xCDFFF ; /* Clear bits */
- cfg|=APIC_DEST_FIELD|APIC_DEST_DM_STARTUP|(((unsigned long)stack)>>12); /* Boot on the stack */
+ cfg&=~0xCDFFF; /* Clear bits */
+ cfg |= (APIC_DEST_FIELD
+ | APIC_DEST_DM_STARTUP
+ | (((int) stack) >> 12) ); /* Boot on the stack */
apic_write(APIC_ICR, cfg); /* Kick the second */
timeout = 0;
do {
- udelay(1000);
- if ((send_status = !(apic_read(APIC_ICR) & 0x00001000)))
- break;
- } while (timeout++ < 1000);
+ udelay(10);
+ } while ( (send_status = (apic_read(APIC_ICR) & 0x1000))
+ && (timeout++ < 1000));
+ udelay(200);
- if (send_status) {
- udelay(1000000);
- apic_write(APIC_ESR, 0);
- accept_status = (apic_read(APIC_ESR) & 0xEF);
- }
+ accept_status = (apic_read(APIC_ESR) & 0xEF);
}
- if (!send_status) /* APIC never delivered?? */
+ if (send_status) /* APIC never delivered?? */
printk("APIC never delivered???\n");
- else if (accept_status) /* Send accept error */
+ if (accept_status) /* Send accept error */
printk("APIC delivery error (%lx).\n", accept_status);
+
+ if( !(send_status || accept_status) )
{
for(timeout=0;timeout<50000;timeout++)
{
if(*((volatile unsigned char *)8192)==0xA5)
printk("Stuck ??\n");
else
- printk("Not responding val=(%lx).\n", *((unsigned long *) stack));
- cpu_present_map&=~(1<<i);
- cpu_number_map[i] = -1;
+ printk("Not responding.\n");
}
}
/* mark "stuck" area as not stuck */
*((volatile unsigned long *)8192) = 0;
}
- else if (i == boot_cpu_id)
- {
- cpu_number_map[i] = 0;
- }
- else
- {
- cpu_number_map[i] = -1;
- }
-
+
+ /*
+ * Make sure we unmap all failed CPUs
+ */
+
+ if (cpu_number_map[i] == -1)
+ cpu_present_map &= ~(1 << i);
}
+
+ /*
+ * Cleanup possible dangling ends...
+ */
+
+ /*
+ * Install writable page 0 entry.
+ */
+
+ cfg = pg0[0];
+ pg0[0] = 3; /* writeable, present, addr 0 */
+ local_invalidate();
+
+ /*
+ * Paranoid: Set warm reset code and vector here back
+ * to default values.
+ */
+
+ CMOS_WRITE(0, 0xf);
+
+ *((volatile long *) 0x467) = 0;
+
+ /*
+ * Restore old page 0 entry.
+ */
+
+ pg0[0] = cfg;
+ local_invalidate();
+
/*
* Allow the user to impress friends.
*/
+
if(cpucount==0)
{
printk("Error: only one processor found.\n");
* Reschedule call back
*/
-void smp_reschedule_irq(int cpl, struct pt_regs *regs)
+void smp_reschedule_irq(int cpl, void *dev_id, struct pt_regs *regs)
{
#ifdef DEBUGGING_SMP_RESCHED
static int ct=0;
* Message call back.
*/
-void smp_message_irq(int cpl, struct pt_regs *regs)
+void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs)
{
int i=smp_processor_id();
/* static int n=0;
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static inline void timer_interrupt(int irq, struct pt_regs * regs)
+static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
do_timer(regs);
* cycle counter value at the time of the timer interrupt, so that
* we later on can estimate the time of day more exactly.
*/
-static void pentium_timer_interrupt(int irq, struct pt_regs * regs)
+static void pentium_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* read Pentium cycle counter */
__asm__(".byte 0x0f,0x31"
:"=a" (((unsigned long *) &last_timer_cc)[0]),
"=d" (((unsigned long *) &last_timer_cc)[1]));
- timer_interrupt(irq, regs);
+ timer_interrupt(irq, NULL, regs);
}
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
void time_init(void)
{
- void (*irq_handler)(int, struct pt_regs *);
+ void (*irq_handler)(int, void *, struct pt_regs *);
xtime.tv_sec = get_cmos_time();
xtime.tv_usec = 0;
"=d" (((unsigned long *) &init_timer_cc)[1]));
}
#endif
- if (request_irq(TIMER_IRQ, irq_handler, 0, "timer") != 0)
+ if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0)
panic("Could not allocate timer IRQ!");
}
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/malloc.h>
#include <linux/random.h>
#include <asm/bitops.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
+#define TIMER_IRQ 0 /* Keep this in sync with time.c */
+
unsigned char cache_21 = 0xff;
unsigned char cache_A1 = 0xff;
/*
* Initial irq handlers.
*/
-struct irqaction {
- void (*handler)(int, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
-};
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction irq_action[16] = {
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+static struct irqaction *irq_action[16] = {
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
int get_irq_list(char *buf)
{
int i, len = 0;
- struct irqaction * action = irq_action;
+ struct irqaction * action;
- for (i = 0 ; i < 16 ; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%3d: %8d %c %s\n",
+ for (i = 0 ; i < 16 ; i++) {
+ action = *(i + irq_action);
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
return len;
}
*/
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
kstat.interrupts[irq]++;
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
- action->handler(irq, regs);
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
}
/*
*/
asmlinkage void do_fast_IRQ(int irq)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
kstat.interrupts[irq]++;
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
- action->handler(irq, NULL);
+ while (action) {
+ action->handler(irq, action->dev_id, NULL);
+ action = action->next;
+ }
}
#define SA_PROBE SA_ONESHOT
-int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char * devname)
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
{
- struct irqaction * action;
+ struct irqaction * action, *tmp = NULL;
unsigned long flags;
if (irq > 15)
return -EINVAL;
- action = irq + irq_action;
- if (action->handler)
- return -EBUSY;
if (!handler)
- return -EINVAL;
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
+ return -EBUSY;
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
if (irqflags & SA_SAMPLE_RANDOM)
rand_initialize_irq(irq);
save_flags(flags);
cli();
+ if (irq == 2)
+ action = &cascade_irq;
+ else if (irq == 13)
+ action = &math_irq;
+ else if (irq == TIMER_IRQ)
+ action = &timer_irq;
+ else
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
- if (!(action->flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
+ if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */
/*
* FIXME: Does the SA_INTERRUPT flag make any sense on MIPS???
*/
set_int_vector(irq,fast_interrupt);
else
set_int_vector(irq,interrupt);
- }
- if (irq < 8) {
+ }
+ if (irq < 8) {
cache_21 &= ~(1<<irq);
outb(cache_21,0x21);
- } else {
+ } else {
cache_21 &= ~(1<<2);
cache_A1 &= ~(1<<(irq-8));
outb(cache_21,0x21);
outb(cache_A1,0xA1);
+ }
}
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq)
+void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+ struct irqaction * tmp = NULL;
unsigned long flags;
if (irq > 15) {
printk("Trying to free free IRQ%d\n",irq);
return;
}
+ if (dev_id) {
+ for (; action; action = action->next) {
+ if (action->dev_id == dev_id) break;
+ tmp = action;
+ }
+ if (!action) {
+ printk("Trying to free free shared IRQ%d\n",irq);
+ return;
+ }
+ } else if (action->flags & SA_SHIRQ) {
+ printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+ return;
+ }
save_flags(flags);
cli();
- if (irq < 8) {
+ if (action && tmp) {
+ tmp->next = action->next;
+ } else {
+ *(irq + irq_action) = action->next;
+ }
+
+ if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
+ memset(action, 0, sizeof(struct irqaction));
+ else
+ kfree_s(action, sizeof(struct irqaction));
+
+ if (!(*(irq + irq_action))) {
+ if (irq < 8) {
cache_21 |= 1 << irq;
outb(cache_21,0x21);
- } else {
+ } else {
cache_A1 |= 1 << (irq-8);
outb(cache_A1,0xA1);
+ }
+ set_int_vector(irq,bad_interrupt);
}
- set_int_vector(irq,bad_interrupt);
- action->handler = NULL;
- action->flags = 0;
- action->mask = 0;
- action->name = NULL;
restore_flags(flags);
}
-static void no_action(int cpl, struct pt_regs * regs) { }
+static void no_action(int cpl, void *dev_id, struct pt_regs * regs) { }
unsigned long probe_irq_on (void)
{
/* first, snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!request_irq(i, no_action, SA_PROBE, "probe")) {
+ if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
enable_irq(i);
irqs |= (1 << i);
}
for (i = 15; i > 0; i--) {
if (irqs & (1 << i) & irqmask) {
irqs ^= (1 << i);
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i)) {
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
+ if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
printk("Unable to get IRQ2 for cascade\n");
break;
default:
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/malloc.h>
#include <asm/system.h>
#include <asm/io.h>
/*
* Irq handlers.
*/
-struct irqaction {
- void (*handler)(int, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
- int notified;
-};
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction irq_action[16] = {
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+static struct irqaction *irq_action[16] = {
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
int get_irq_list(char *buf)
{
int i, len = 0;
- struct irqaction * action = irq_action;
+ struct irqaction * action;
- for (i = 0 ; i < 16 ; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%2d: %8d %c %s\n",
+ for (i = 0 ; i < 16 ; i++) {
+ action = *(i + irq_action);
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %8d %c %s",
i, kstat.interrupts[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
return len;
}
asmlinkage void handle_IRQ(struct pt_regs *regs)
{
int irq, s;
- struct irqaction *action;
+ struct irqaction * action;
intr_count++;
/* Figure out IRQ#, etc. */
outb(0x0C, 0x20); /* Poll interrupt controller */
outb(cache_21 | (1<<irq), 0x21);
outb(0x20, 0x20);
}
- action = irq + irq_action;
+ action = *(irq + irq_action);
kstat.interrupts[irq]++;
- if (action->handler)
- {
- action->handler(irq, regs);
- } else
- {
+ while (action) {
+ if (action->handler)
+ {
+ action->handler(irq, action->dev_id, regs);
+ } else
+ {
_printk("Bogus interrupt #%d\n", irq);
+ }
+ action = action->next;
}
if (_disable_interrupts() && !action->notified)
{
#define SA_PROBE SA_ONESHOT
-int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char * devname)
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
{
- struct irqaction * action;
+ struct irqaction * action, *tmp = NULL;
unsigned long flags;
#if 0
#endif
if (irq > 15)
return -EINVAL;
- action = irq + irq_action;
- if (action->handler)
- return -EBUSY;
if (!handler)
- return -EINVAL;
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
+ return -EBUSY;
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
save_flags(flags);
cli();
+ if (irq == 2)
+ action = &cascade_irq;
+ else if (irq == 13)
+ action = &math_irq;
+ else if (irq == TIMER_IRQ)
+ action = &timer_irq;
+ else
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
#if 0
- if (!(action->flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */
+ if (!(action->flags & SA_PROBE)) { /* SA_ONESHOT is used by probing */
if (action->flags & SA_INTERRUPT)
- set_intr_gate(0x20+irq,fast_interrupt[irq]);
+ set_intr_gate(0x20+irq,fast_interrupt[irq]);
else
- set_intr_gate(0x20+irq,interrupt[irq]);
- }
+ set_intr_gate(0x20+irq,interrupt[irq]);
+ }
#endif
- if (irq < 8) {
+ if (irq < 8) {
cache_21 &= ~(1<<irq);
outb(cache_21,0x21);
- } else {
+ } else {
cache_21 &= ~(1<<2);
cache_A1 &= ~(1<<(irq-8));
outb(cache_21,0x21);
outb(cache_A1,0xA1);
+ }
}
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq)
+void free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+ struct irqaction * tmp = NULL;
unsigned long flags;
if (irq > 15) {
printk("Trying to free free IRQ%d\n",irq);
return;
}
+ if (dev_id) {
+ for (; action; action = action->next) {
+ if (action->dev_id == dev_id) break;
+ tmp = action;
+ }
+ if (!action) {
+ printk("Trying to free free shared IRQ%d\n",irq);
+ return;
+ }
+ } else if (action->flags & SA_SHIRQ) {
+ printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+ return;
+ }
save_flags(flags);
cli();
- if (irq < 8) {
+ if (action && tmp) {
+ tmp->next = action->next;
+ } else {
+ *(irq + irq_action) = action->next;
+ }
+
+ if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
+ memset(action, 0, sizeof(struct irqaction));
+ else
+ kfree_s(action, sizeof(struct irqaction));
+
+ if (!(*(irq + irq_action))) {
+ if (irq < 8) {
cache_21 |= 1 << irq;
outb(cache_21,0x21);
- } else {
+ } else {
cache_A1 |= 1 << (irq-8);
outb(cache_A1,0xA1);
- }
+ }
#if 0
- set_intr_gate(0x20+irq,bad_interrupt[irq]);
+ set_intr_gate(0x20+irq,bad_interrupt[irq]);
#endif
- action->handler = NULL;
- action->flags = 0;
- action->mask = 0;
- action->name = NULL;
+ }
+
restore_flags(flags);
}
-static void no_action(int cpl, struct pt_regs * regs) { }
+static void no_action(int cpl, void *dev_id, struct pt_regs * regs) { }
unsigned /*int*/ long probe_irq_on (void)
{
/* first, snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!request_irq(i, no_action, SA_PROBE, "probe")) {
+ if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
enable_irq(i);
irqs |= (1 << i);
}
for (i = 15; i > 0; i--) {
if (irqs & (1 << i) & irqmask) {
irqs ^= (1 << i);
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i)) {
- free_irq(i);
+ free_irq(i, NULL);
}
}
#ifdef DEBUG
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade"))
+ if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
printk("Unable to get IRQ2 for cascade\n");
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/malloc.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
/*
* Initial irq handlers.
*/
-struct irqaction {
- void (*handler)(int, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
-};
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction math_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction irq_action[16] = {
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
+static struct irqaction *irq_action[16] = {
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
};
-
int
get_irq_list(char *buf)
{
int i, len = 0;
- struct irqaction * action = irq_action;
-
- for (i = 0 ; i < 16 ; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%2d: %8d %c %s\n",
- i, kstat.interrupts[i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
+ struct irqaction * action;
+
+ for (i = 0 ; i < 16 ; i++) {
+ action = *(i + irq_action);
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %8d %c %s",
+ i, kstat.interrupts[i],
+ (action->flags & SA_INTERRUPT) ? '+' : ' ',
+ action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
return len;
}
void
-free_irq(unsigned int irq)
+free_irq(unsigned int irq, void *dev_id)
{
- struct irqaction * action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
+ struct irqaction * tmp = NULL;
unsigned long flags;
if (irq > 14) { /* 14 irq levels on the sparc */
printk("Trying to free bogus IRQ %d\n", irq);
return;
}
- if (!action->handler) {
- printk("Trying to free free IRQ%d\n", irq);
- return;
- }
+ if (!action->handler) {
+ printk("Trying to free free IRQ%d\n",irq);
+ return;
+ }
+ if (dev_id) {
+ for (; action; action = action->next) {
+ if (action->dev_id == dev_id) break;
+ tmp = action;
+ }
+ if (!action) {
+ printk("Trying to free free shared IRQ%d\n",irq);
+ return;
+ }
+ } else if (action->flags & SA_SHIRQ) {
+ printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+ return;
+ }
save_flags(flags); cli();
- disable_irq(irq);
- action->handler = NULL;
- action->flags = 0;
- action->mask = 0;
- action->name = NULL;
+ if (action && tmp) {
+ tmp->next = action->next;
+ } else {
+ *(irq + irq_action) = action->next;
+ }
+ kfree_s(action, sizeof(struct irqaction));
+
+ if (!(*(irq + irq_action))) {
+ disable_irq(irq);
+ }
+
restore_flags(flags);
}
unexpected_irq(int irq, struct pt_regs * regs)
{
int i;
+ struct irqaction * action = *(irq + irq_action);
printk("IO device interrupt, irq = %d\n", irq);
printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
regs->npc, regs->u_regs[14]);
printk("Expecting: ");
for (i = 0; i < 16; i++)
- if (irq_action[i].handler)
- prom_printf("[%s:%d:0x%x] ", irq_action[i].name, (int) i,
- (unsigned int) irq_action[i].handler);
+ if (action->handler)
+ prom_printf("[%s:%d:0x%x] ", action->name, (int) i,
+ (unsigned int) action->handler);
printk("AIEEE\n");
panic("bogus interrupt received");
}
void
handler_irq(int irq, struct pt_regs * regs)
{
- struct irqaction * action = irq_action + irq;
+ struct irqaction * action = *(irq + irq_action);
kstat.interrupts[irq]++;
- if (!action->handler)
- unexpected_irq(irq, regs);
- else
- action->handler(irq, regs);
+ while (action) {
+ if (!action->handler)
+ unexpected_irq(irq, action->dev_id, regs);
+ else
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
}
/*
asmlinkage void
do_IRQ(int irq, struct pt_regs * regs)
{
- struct irqaction *action = irq + irq_action;
+ struct irqaction * action = *(irq + irq_action);
kstat.interrupts[irq]++;
- action->handler(irq, regs);
+ while (action) {
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ }
return;
}
int
request_fast_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char *devname)
+ unsigned long irqflags, const char *devname, void *dev_id)
+)
{
- struct irqaction *action;
+ struct irqaction * action, *tmp = NULL;
unsigned long flags;
if(irq > 14)
return -EINVAL;
- action = irq + irq_action;
- if(action->handler)
+ if (!handler)
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
return -EBUSY;
- if(!handler)
- return -EINVAL;
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
save_flags(flags); cli();
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
/* Dork with trap table if we get this far. */
sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one =
SPARC_BRANCH((unsigned long) handler,
action->flags = irqflags;
action->mask = 0;
action->name = devname;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
+ }
restore_flags(flags);
return 0;
int
request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
- unsigned long irqflags, const char * devname)
+ unsigned long irqflags, const char * devname, void *dev_id)
{
- struct irqaction *action;
+ struct irqaction * action, *tmp = NULL;
unsigned long flags;
if(irq > 14)
return -EINVAL;
- action = irq + irq_action;
- if(action->handler)
+ if (!handler)
+ return -EINVAL;
+ action = *(irq + irq_action);
+ if (action) {
+ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
+ for (tmp = action; tmp->next; tmp = tmp->next);
+ } else {
return -EBUSY;
- if(!handler)
- return -EINVAL;
-
+ }
+ if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
+ printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+ return -EBUSY;
+ }
+ }
save_flags(flags); cli();
+ action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+ if (!action) {
+ restore_flags(flags);
+ return -ENOMEM;
+ }
+
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
action->name = devname;
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ if (tmp) {
+ tmp->next = action;
+ } else {
+ *(irq + irq_action) = action;
+ }
enable_irq(irq);
if(irq == 10)
probe_clock();
bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
comment 'Note: most of these also require special kernel boot parameters'
- bool ' DTC-2278 chipset support' CONFIG_BLK_DEV_DTC2278
- bool ' Holtek HT6560B chipset support' CONFIG_BLK_DEV_HT6560B
- bool ' QDI QD6580 chipset support' CONFIG_BLK_DEV_QD6580
- bool ' UMC 8672 chipset support' CONFIG_BLK_DEV_UMC8672
- bool ' ALI M1439/M1445 chipset support' CONFIG_BLK_DEV_ALI14XX
+ bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278
+ bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B
+ bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
+ bool ' UMC 8672 support' CONFIG_BLK_DEV_UMC8672
+ bool ' ALI M1439/M1445 support' CONFIG_BLK_DEV_ALI14XX
fi
fi
The hdparm.c program for controlling various features is now packaged
separately. Look for it on your favorite linux FTP site.
--mlord@bnr.ca
+-mlord@pobox.com
README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.3.xx)
================================================================================
-Supported by: mlord@bnr.ca -- disks, interfaces, probing
+Supported by: mlord@pobox.com -- disks, interfaces, probing
snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
+-----------------------------------------------------------------+
NEW! - ide-cd.c now supports door locking and auto-loading.
- Also preliminary support for multisession
and direct reads of audio data.
-NEW! - the hdparm-2.6 package can be used to set PIO modes for some chipsets.
+NEW! - the hdparm-2.7 package can be used to set PIO modes for some chipsets.
For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
Look for this support to be added to the kernel soon.
-*** IMPORTANT NOTICES (for kernel versions prior to 1.3.22)
-*** =================
-*** "CMD" EIDE Interfaces will not (by default) work *reliably* when drives
-*** are attached to the second interface. This is due to a flaw in the
-*** hardware. To "fix" this, supply the special kernel "command line"
-*** parameter to LILO or LOADLIN: ide1=serialize
-***
-*** "CMD 640B" EIDE Interfaces will not work *reliably* when "hdparm -u1"
-*** (interrupt unmasking) is used. This is due to a flaw in the hardware,
-*** and is only a problem when "hdparm -u1" is used after booting.
-***
-*** "RZ1000" EIDE Interfaces will also not work *reliably* when "hdparm -u1"
-*** (interrupt unmasking) is used. This is due to a flaw in the hardware,
-*** and is only a problem when "hdparm -u1" is used after booting.
-***
-*** Failure to abide by these restrictions can cause severe data corruption!
-
-
*** IMPORTANT NOTICES (for kernel versions after 1.3.21)
*** =================
*** PCI versions of the CMD640 and RZ1000 interfaces are now detected
under control of ide.c. To have ide.c also "take over" the primary
IDE port in this situation, use the "command line" parameter: ide0=0x1f0
-mlord@bnr.ca
+mlord@pobox.com
snyder@fnald0.fnal.gov
================================================================================
For really high end systems, go for fast/wide 7200rpm SCSI. But it'll cost ya!
-mlord@bnr.ca
+mlord@pobox.com
================================================================================
EIDE card compatibility reports:
const char* name;
int mode;
} drives_ra[] = {
+ { "QUANTUM LIGHTNING 540A", 0 },
{ "ST3655A", 0 },
{ "SAMSUNG", 0 }, /* Be conservative */
{ NULL, 0 }
* /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
* filesystem corrupted with -u1, but under heavy disk load only :-)
*
- * This chipset is now forced to use the "serialize" feature,
+ * This card is now forced to use the "serialize" feature,
* and irq-unmasking is disallowed. If io_32bit is enabled,
* it must be done for BOTH drives on each interface.
+ *
+ * This code was written for the DTC2278E, but might work with any of these:
+ *
+ * DTC2278S has only a single IDE interface.
+ * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
+ * DTC2278E has onboard BIOS, while the others do not.
+ *
+ * There may be a fourth controller type. The S and D versions use the
+ * Winbond chip, and I think the E version does also.
+ *
*/
static void sub22 (char b, char c)
{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
/* interrupt handler */
-static void floppy_interrupt(int irq, struct pt_regs * regs)
+static void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
void (*handler)(void) = DEVICE_INTR;
DPRINT("request list destroyed in floppy request done\n");
return;
}
+
if (uptodate){
/* maintain values for invalidation on geometry
* change */
* Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
* in the early extended-partition checks and added DM partitions
*
- * Support for DiskManager v6.0x added by Mark Lord (mlord@bnr.ca)
+ * Support for DiskManager v6.0x added by Mark Lord,
* with information provided by OnTrack. This now works for linux fdisk
* and LILO, as well as loadlin and bootln. Note that disks other than
* /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
extern int scsi_dev_init(void);
extern int net_dev_init(void);
-static void print_minor_name (struct gendisk *hd, int minor)
+/*
+ * disk_name() is used by genhd.c and md.c.
+ * It formats the devicename of the indicated disk
+ * into the supplied buffer, and returns a pointer
+ * to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf)
{
- unsigned int unit = minor >> hd->minor_shift;
- unsigned int part = minor & ((1 << hd->minor_shift) - 1);
+ unsigned int part;
+ const char *maj = hd->major_name;
+ char unit = (minor >> hd->minor_shift) + 'a';
#ifdef CONFIG_BLK_DEV_IDE
/*
* IDE devices use multiple major numbers, but the drives
* are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
- * This requires some creative handling here to find the
- * correct name to use, with some help from ide.c
+ * This requires special handling here.
*/
- if (!strcmp(hd->major_name,"ide")) {
- char name[16]; /* more than large enough */
- strcpy(name, hd->real_devices); /* courtesy ide.c */
- name[strlen(name)-1] += unit;
- printk(" %s", name);
- } else
+ switch (hd->major) {
+ case IDE3_MAJOR:
+ unit += 2;
+ case IDE2_MAJOR:
+ unit += 2;
+ case IDE1_MAJOR:
+ unit += 2;
+ case IDE0_MAJOR:
+ maj = "hd";
+ }
#endif
- printk(" %s%c", hd->major_name, 'a' + unit);
+ part = minor & ((1 << hd->minor_shift) - 1);
if (part)
- printk("%d", part);
+ sprintf(buf, "%s%c%d", maj, unit, part);
else
- printk(":");
+ sprintf(buf, "%s%c", maj, unit);
+ return buf;
}
static void add_partition (struct gendisk *hd, int minor, int start, int size)
{
+ char buf[8];
hd->part[minor].start_sect = start;
hd->part[minor].nr_sects = size;
- print_minor_name(hd, minor);
+ printk(" %s", disk_name(hd, minor, buf));
}
static inline int is_extended_partition(struct partition *p)
{
static int first_time = 1;
unsigned long first_sector;
+ char buf[8];
if (first_time)
printk("Partition check:\n");
return;
}
- printk(" ");
- print_minor_name(hd, MINOR(dev));
+ printk(" %s:", disk_name(hd, MINOR(dev), buf));
#ifdef CONFIG_MSDOS_PARTITION
if (msdos_partition(hd, dev, first_sector))
return;
* in the early extended-partition checks and added DM partitions
*
* IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
- * and general streamlining by mlord@bnr.ca (Mark Lord).
+ * and general streamlining by Mark Lord.
*/
#define DEFAULT_MULT_COUNT 0 /* set to 0 to disable multiple mode at boot */
NULL /* next */
};
-static void hd_interrupt(int irq, struct pt_regs *regs)
+static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
void (*handler)(void) = DEVICE_INTR;
special_op[i] = 1;
}
if (NR_HD) {
- if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd")) {
+ if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
printk("hd: unable to get IRQ%d for the harddisk driver\n",HD_IRQ);
NR_HD = 0;
} else {
/*
- * linux/drivers/block/ide.c Version 5.28 Feb 11, 1996
+ * linux/drivers/block/ide.c Version 5.30 Feb 27, 1996
*
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/
* | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI).
* |
* | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
- * | and general streamlining by Mark Lord (mlord@bnr.ca).
+ * | and general streamlining by Mark Lord (mlord@pobox.com).
*
* October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
*
- * Mark Lord (mlord@bnr.ca) (IDE Perf.Pkg)
+ * Mark Lord (mlord@pobox.com) (IDE Perf.Pkg)
* Delman Lee (delman@mipg.upenn.edu) ("Mr. atdisk2")
* Petri Mattila (ptjmatti@kruuna.helsinki.fi) (EIDE stuff)
* Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom)
*
- * Maintained by Mark Lord (mlord@bnr.ca): ide.c, ide.h, triton.c, hd.c, ..
+ * Maintained by Mark Lord (mlord@pobox.com): ide.c, ide.h, triton.c, hd.c, ..
*
* This was a rewrite of just about everything from hd.c, though some original
* code is still sprinkled about. Think of it as a major evolution, with
* force io_32bit to be the same on drive pairs of dtc2278
* improved IDE tape error handling, and tape DMA support
* bugfix in ide_do_drive_cmd() for cdroms + serialize
+ * Version 5.29 fixed non-IDE check for too many physical heads
+ * don't use LBA if capacity is smaller than CHS
+ * Version 5.30 remove real_devices kludge, formerly used by genhd.c
*
* Some additional driver compile-time options are in ide.h
*
static unsigned long current_capacity (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
- unsigned long capacity;
+ unsigned long capacity = drive->cyl * drive->head * drive->sect;
if (!drive->present)
return 0;
if (drive->media != ide_disk)
return 0x7fffffff; /* cdrom or tape */
+ drive->select.b.lba = 0;
/* Determine capacity, and use LBA if the drive properly supports it */
if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
- drive->select.b.lba = 1;
- capacity = id->lba_capacity;
- } else {
- drive->select.b.lba = 0;
- capacity = drive->cyl * drive->head * drive->sect;
+ if (id->lba_capacity >= capacity) {
+ capacity = id->lba_capacity;
+ drive->select.b.lba = 1;
+ }
}
return (capacity - drive->sect0);
}
drive->part[0].start_sect = -1; /* skip partition check */
}
}
- /*
- * The partition check in genhd.c needs this string to identify
- * our minor devices by name for display purposes.
- * Note that doing this will prevent us from working correctly
- * if ever called a second time for this major (never happens).
- */
- gd->real_devices = hwif->drives[0].name; /* name of first drive */
}
/*
if ((tmp = GET_ERR()) == 1)
printk("success\n");
else {
+#if FANCY_STATUS_DUMPS
printk("master: ");
switch (tmp & 0x7f) {
case 1: printk("passed");
if (tmp & 0x80)
printk("; slave: failed");
printk("\n");
+#else
+ printk("failed\n");
+#endif /* FANCY_STATUS_DUMPS */
}
}
hwgroup->poll_timeout = 0; /* done polling */
} else
drive->mult_req = 0;
} else if (s->all) {
+ int special = s->all;
s->all = 0;
- printk("%s: bad special flag: 0x%02x\n", drive->name, s->all);
+ printk("%s: bad special flag: 0x%02x\n", drive->name, special);
}
}
do_hwgroup_request (ide_hwifs[0].hwgroup);
}
+#if MAX_HWIFS > 1
static void do_ide1_request (void) /* invoked with cli() */
{
do_hwgroup_request (ide_hwifs[1].hwgroup);
}
+#endif
+#if MAX_HWIFS > 2
static void do_ide2_request (void) /* invoked with cli() */
{
do_hwgroup_request (ide_hwifs[2].hwgroup);
}
+#endif
+#if MAX_HWIFS > 3
static void do_ide3_request (void) /* invoked with cli() */
{
do_hwgroup_request (ide_hwifs[3].hwgroup);
}
+#endif
static void timer_expiry (unsigned long data)
{
/*
* entry point for all interrupts, caller does cli() for us
*/
-static void ide_intr (int irq, struct pt_regs *regs)
+static void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{
ide_hwgroup_t *hwgroup = irq_to_hwgroup[irq];
ide_handler_t *handler;
ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap);
ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap);
+#ifdef CONFIG_BLK_DEV_IDEATAPI
/*
* Check for an ATAPI device
*/
-
if (cmd == WIN_PIDENTIFY) {
byte type = (id->config >> 8) & 0x1f;
printk("%s: %s, ATAPI ", drive->name, id->model);
printk("- not supported by this kernel\n");
return;
}
+#endif /* CONFIG_BLK_DEV_IDEATAPI */
/* check for removeable disks (eg. SYQUEST), ignore 'WD' drives */
if (id->config & (1<<7)) { /* removeable disk ? */
#endif /* CONFIG_BLK_DEV_IDECD */
else {
drive->present = 0; /* nuke it */
- return 1; /* drive was found */
- }
- }
- if (drive->media == ide_disk && !drive->select.b.lba) {
- if (!drive->head || drive->head > 16) {
- printk("%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
- drive->name, drive->head);
- drive->present = 0;
}
}
return 1; /* drive was found */
}
/*
- * This routine only knows how to look for drive units 0 and 1
- * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
+ * This routine only knows how to look for drive units 0 and 1
+ * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/
-static void probe_for_drives (ide_hwif_t *hwif)
+static void probe_hwif (ide_hwif_t *hwif)
{
unsigned int unit;
unsigned long flags;
save_flags(flags);
-#if (MAX_DRIVES > 2)
- printk("%s: probing for first 2 of %d possible drives\n", hwif->name, MAX_DRIVES);
-#endif
sti(); /* needed for jiffies and irq probing */
/*
* Second drive should only exist if first drive was found,
- * but a lot of cdrom drives seem to be configured as slave-only
+ * but a lot of cdrom drives are configured as single slaves.
*/
- for (unit = 0; unit < 2; ++unit) { /* note the hardcoded '2' */
- ide_drive_t *drive = &hwif->drives[unit];
- (void) probe_for_drive (drive);
- }
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
- if (drive->present) {
+ (void) probe_for_drive (drive);
+ if (drive->present && drive->media == ide_disk) {
+ if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
+ printk("%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
+ drive->name, drive->head);
+ drive->present = 0;
+ }
+ }
+ if (drive->present && !hwif->present) {
hwif->present = 1;
request_region(hwif->io_base, 8, hwif->name);
request_region(hwif->ctl_port, 1, hwif->name);
- break;
}
}
restore_flags(flags);
* Grab the irq if we don't already have it from a previous hwif
*/
if (hwgroup == NULL) {
- if (request_irq(irq, ide_intr, SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name)) {
+ if (request_irq(irq, ide_intr, SA_INTERRUPT|SA_SAMPLE_RANDOM, hwif->name, NULL)) {
restore_flags(flags);
printk(" -- FAILED!");
return 1;
* Check for serialization with ide1.
* This code depends on us having already taken care of ide1.
*/
- if (hwif->serialized && hwif->name[3] == '0' && ide_hwifs[1].present)
+ if (hwif->serialized && hwif->index == 0 && ide_hwifs[1].present)
hwgroup = ide_hwifs[1].hwgroup;
/*
* If this is the first interface in a group,
if (!hwif->noprobe) {
if (hwif->io_base == HD_DATA)
probe_cmos_for_drives (hwif);
- probe_for_drives (hwif);
+ probe_hwif (hwif);
}
if (hwif->present) {
if (!hwif->irq) {
hwif->present = 0; /* we set it back to 1 if all is ok below */
switch (hwif->major) {
case IDE0_MAJOR: rfn = &do_ide0_request; break;
+#if MAX_HWIFS > 1
case IDE1_MAJOR: rfn = &do_ide1_request; break;
+#endif
+#if MAX_HWIFS > 2
case IDE2_MAJOR: rfn = &do_ide2_request; break;
+#endif
+#if MAX_HWIFS > 3
case IDE3_MAJOR: rfn = &do_ide3_request; break;
+#endif
default:
printk("%s: request_fn NOT DEFINED\n", hwif->name);
continue;
#define PARTN_BITS 6 /* number of minor dev bits for partitions */
#define PARTN_MASK ((1<<PARTN_BITS)-1) /* a useful bit mask */
#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */
+#ifndef MAX_HWIFS
#define MAX_HWIFS 4 /* an arbitrary, but realistic limit */
+#endif
#define SECTOR_WORDS (512 / 4) /* number of 32bit words per sector */
/*
{ "QUANTUM LPS270A", 3 },
{ "QUANTUM LPS365A", 3 },
{ "QUANTUM LPS540A", 3 },
+ { "QUANTUM LIGHTNING 540A", 3 },
{ "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */
/* 1080A works fine in mode4 with triton */
{ NULL, 0 }
if (blk_size[major][MINOR(bh->b_dev)] < (sector + count)>>1) {
bh->b_state = 0;
printk("attempt to access beyond end of device\n");
+ printk("%s: rw=%d, want=%d, limit=%d\n", kdevname(bh->b_dev),
+ rw, (sector + count)>>1, blk_size[major][MINOR(bh->b_dev)]);
return;
}
/* Uhhuh.. Nasty dead-lock possible here.. */
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
+#include <linux/genhd.h>
#include <errno.h>
#define MAJOR_NR MD_MAJOR
static char name[10]; /* This should be long
enough for a device name ! */
struct gendisk *hd=find_gendisk (dev);
- char base_name;
- int minor=MINOR(dev);
if (!hd)
{
return (name);
}
- base_name = (hd->major == IDE1_MAJOR) ? 'c' : 'a';
- sprintf(name, "%s%c%d",
- hd->major_name,
- base_name + (minor >> hd->minor_shift),
- minor & ((1 << hd->minor_shift) - 1));
- return (name);
+ return disk_name (hd, MINOR(dev), name); /* routine in genhd.c */
}
*/
/*
- * Principal Author/Maintainer: mlord@bnr.ca (Mark Lord)
+ * Principal Author/Maintainer: mlord@pobox.com (Mark Lord)
*
* This file provides support for disabling the buggy read-ahead
* mode of the RZ1000 IDE chipset, commonly used on Intel motherboards.
* - like most Conner models, this drive proves that even a fast interface
* cannot improve slow media. Both DMA and PIO peak around 3.5MB/sec.
*
- * If you have any drive models to add, email your results to: mlord@bnr.ca
+ * Maxtor 71260AT (1204Meg w/256kB buffer), DMA mword0/sword2, PIO mode3.
+ * - works with DMA, giving 3-4MB/sec performance, about the same as mode3.
+ *
+ * If you have any drive models to add, email your results to: mlord@pobox.com
* Keep an eye on /var/adm/messages for "DMA disabled" messages.
*
* Some people have reported trouble with Intel Zappa motherboards.
* known to work fine with this interface under Linux.
*/
const char *good_dma_drives[] = {"Micropolis 2112A",
+ "Maxtor 71260 AT",
"CONNER CTMA 4000"};
/*
for (i = 0; i < xd_drives; i++)
printk("xd_geninit: drive %d geometry - heads = %d, cylinders = %d, sectors = %d\n",i,xd_info[i].heads,xd_info[i].cylinders,xd_info[i].sectors);
- if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT harddisk")) {
+ if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT harddisk", NULL)) {
if (request_dma(xd_dma,"xd")) {
printk("xd_geninit: unable to get DMA%d\n",xd_dma);
- free_irq(xd_irq);
+ free_irq(xd_irq, NULL);
}
}
else
}
/* xd_interrupt_handler: interrupt service routine */
-static void xd_interrupt_handler(int irq, struct pt_regs * regs)
+static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
{
if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
#ifdef DEBUG_OTHER
}
static void
-cdu31a_interrupt(int irq, struct pt_regs *regs)
+cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char val;
if (cdu31a_irq > 0)
{
- if (request_irq(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, "cdu31a"))
+ if (request_irq(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT, "cdu31a", NULL))
{
printk("Unable to grab IRQ%d for the CDU31A driver\n", cdu31a_irq);
cdu31a_irq = 0;
as there seems so reason for this to happen.
*/
-static void cm206_interrupt(int sig, struct pt_regs * regs) /* you rang? */
+static void cm206_interrupt(int sig, void *dev_id, struct pt_regs * regs) /* you rang? */
{
volatile ush fool;
cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error,
return;
}
case 3:
- free_irq(cm206_irq);
+ free_irq(cm206_irq, NULL);
case 2:
case 1:
kfree(cd);
else printk(" single");
printk(" speed drive");
if (e & dcf_motorized_tray) printk(", motorized tray");
- if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206")) {
+ if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
printk("\nUnable to reserve IRQ---aborted\n");
cleanup(2);
return -EIO;
*/
static void
-mcd_interrupt(int irq, struct pt_regs * regs)
+mcd_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
int st;
/* don't get the IRQ until we know for sure the drive is there */
- if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD"))
+ if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))
{
printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
return -EIO;
return;
}
release_region(mcd_port,4);
- free_irq(mcd_irq);
+ free_irq(mcd_irq, NULL);
printk("mcd module released.\n");
}
#endif MODULE
structure fops. */
/* ??? exported by the mcdx_sigaction struct */
-static void mcdx_intr(int, struct pt_regs*);
+static void mcdx_intr(int, void *, struct pt_regs*);
/* exported by file_ops */
static int mcdx_open(struct inode*, struct file*);
}
static void
-mcdx_intr(int irq, struct pt_regs* regs)
+mcdx_intr(int irq, void *dev_id, struct pt_regs* regs)
{
struct s_drive_stuff *stuffp;
unsigned char x;
stuffp = mcdx_stuffp[i];
if (!stuffp) continue;
release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
- free_irq(stuffp->irq);
+ free_irq(stuffp->irq, NULL);
if (stuffp->toc) {
TRACE((MALLOC, "cleanup_module() free toc @ %p\n", stuffp->toc));
kfree(stuffp->toc);
TRACE((INIT, "init() subscribe irq and i/o\n"));
mcdx_irq_map[stuffp->irq] = stuffp;
- if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME)) {
+ if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME, NULL)) {
WARN(("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
MCDX,
stuffp->wreg_data, stuffp->irq, stuffp->irq));
}
static void
-cdu535_interrupt(int irq, struct pt_regs *regs)
+cdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
disable_interrupts();
if (cdu535_irq_wait != NULL)
#endif
if (sony535_irq_used > 0) {
if (request_irq(sony535_irq_used, cdu535_interrupt,
- SA_INTERRUPT, CDU535_HANDLE)) {
+ SA_INTERRUPT, CDU535_HANDLE, NULL)) {
printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
" driver; polling instead.\n", sony535_irq_used);
sony535_irq_used = 0;
struct fasync_struct *fasync;
} mouse;
-void mouse_interrupt(int irq, struct pt_regs * regs)
+void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
char dx, dy, buttons;
return;
ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */
mouse.ready = 0;
- free_irq(ATIXL_MOUSE_IRQ);
+ free_irq(ATIXL_MOUSE_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
return -EINVAL;
if (mouse.active++)
return 0;
- if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse")) {
+ if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse", NULL)) {
mouse.active--;
return -EBUSY;
}
mouse_irq=ints[1];
}
-static void mouse_interrupt(int irq, struct pt_regs *regs)
+static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
char dx, dy;
unsigned char buttons;
if (--mouse.active)
return;
MSE_INT_OFF();
- free_irq(mouse_irq);
+ free_irq(mouse_irq, NULL);
MOD_DEC_USE_COUNT;
}
return -EINVAL;
if (mouse.active++)
return 0;
- if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse")) {
+ if (request_irq(mouse_irq, mouse_interrupt, 0, "busmouse", NULL)) {
mouse.active--;
return -EBUSY;
}
console_driver.num = MAX_NR_CONSOLES;
console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
console_driver.init_termios = tty_std_termios;
- console_driver.flags = TTY_DRIVER_REAL_RAW;
+ console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
console_driver.refcount = &console_refcount;
console_driver.table = console_table;
console_driver.termios = console_termios;
* while we are probing for submarines.
*/
static void
-cy_probe(int irq, struct pt_regs *regs)
+cy_probe(int irq, void *dev_id, struct pt_regs *regs)
{
int save_xir, save_car;
int index = 0; /* probing interrupts is only for ISA */
received, out buffer empty, modem change, etc.
*/
static void
-cy_interrupt(int irq, struct pt_regs *regs)
+cy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct tty_struct *tty;
int status;
for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
if (!(mask & dontgrab)
- && !request_irq(i, cy_probe, SA_INTERRUPT, "serial probe")) {
+ && !request_irq(i, cy_probe, SA_INTERRUPT, "serial probe", NULL)) {
irq_lines |= mask;
}
}
for (i = 0; i < 16; i++) {
if (irq_lines & (1 << i))
- free_irq(i);
+ free_irq(i,NULL);
}
} /* free_all_interrupts */
for (i = 0; i < NR_CARDS; i++) {
if (cy_card[i].base_addr != 0)
{
- free_irq(cy_card[i].irq);
+ free_irq(cy_card[i].irq,NULL);
}
}
}
}
/* allocate IRQ */
- if(request_irq(cy_isa_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
+ if(request_irq(cy_isa_irq,cy_interrupt,SA_INTERRUPT,"cyclades",NULL))
{
printk("Cyclom-Y/ISA found at 0x%x but could not allocate interrupt IRQ#%d.\n",
(unsigned int) cy_isa_address,cy_isa_irq);
}
/* allocate IRQ */
- if(request_irq(cy_pci_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
+ if(request_irq(cy_pci_irq,cy_interrupt,SA_INTERRUPT,"cyclades",NULL))
{
printk("Cyclom-Y/PCI found at 0x%x but could not allocate interrupt IRQ%d.\n",
(unsigned int) cy_pci_address,cy_pci_irq);
e0_keys[scancode - 128];
}
-static void keyboard_interrupt(int irq, struct pt_regs *regs)
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char scancode, keycode;
static unsigned int prev_scancode = 0; /* remember E0, E1 */
ttytab = console_driver.table;
bh_base[KEYBOARD_BH].routine = kbd_bh;
- request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard");
+ request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
request_region(0x60,16,"kbd");
#ifdef INIT_KBD
initialize_kbd();
return 0;
}
-static void lp_interrupt(int irq, struct pt_regs *regs)
+static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct lp_struct *lp = &lp_table[0];
return -ENOMEM;
}
- ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer");
+ ret = request_irq(irq, lp_interrupt, SA_INTERRUPT, "printer", NULL);
if (ret) {
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
unsigned int irq;
if ((irq = LP_IRQ(minor))) {
- free_irq(irq);
+ free_irq(irq, NULL);
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
}
}
if (oldirq) {
- free_irq(oldirq);
+ free_irq(oldirq, NULL);
}
if (newirq) {
/* Install new irq */
- if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer"))) {
+ if ((retval = request_irq(newirq, lp_interrupt, SA_INTERRUPT, "printer", NULL))) {
if (oldirq) {
/* restore old irq */
- request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer");
+ request_irq(oldirq, lp_interrupt, SA_INTERRUPT, "printer", NULL);
} else {
/* We don't need the buffer */
kfree_s(lp->lp_buffer, LP_BUFFER_SIZE);
static struct mouse_status mouse;
-static void ms_mouse_interrupt(int irq, struct pt_regs * regs)
+static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
char dx, dy;
unsigned char buttons;
return;
MS_MSE_INT_OFF();
mouse.ready = 0;
- free_irq(MOUSE_IRQ);
+ free_irq(MOUSE_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
return -EINVAL;
if (mouse.active++)
return 0;
- if (request_irq(MOUSE_IRQ, ms_mouse_interrupt, 0, "MS Busmouse")) {
+ if (request_irq(MOUSE_IRQ, ms_mouse_interrupt, 0, "MS Busmouse", NULL)) {
mouse.active--;
return -EBUSY;
}
* is waiting in the keyboard/aux controller.
*/
-static void aux_interrupt(int cpl, struct pt_regs * regs)
+static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
*/
#ifdef CONFIG_82C710_MOUSE
-static void qp_interrupt(int cpl, struct pt_regs * regs)
+static void qp_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
{
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
poll_aux_status();
outb_p(AUX_DISABLE,AUX_COMMAND); /* Disable Aux device */
poll_aux_status();
- free_irq(AUX_IRQ);
+ free_irq(AUX_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
if (!poll_qp_status())
printk("Warning: Mouse device busy in release_qp()\n");
- free_irq(QP_IRQ);
+ free_irq(QP_IRQ, NULL);
MOD_DEC_USE_COUNT;
}
#endif
return -EBUSY;
}
queue->head = queue->tail = 0; /* Flush input queue */
- if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse")) {
+ if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL)) {
aux_count--;
return -EBUSY;
}
if (qp_count++)
return 0;
- if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse")) {
+ if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse", NULL)) {
qp_count--;
return -EBUSY;
}
qp_count--;
status &= ~(QP_ENABLE|QP_INTS_ON);
outb_p(status, qp_status);
- free_irq(QP_IRQ);
+ free_irq(QP_IRQ, NULL);
return -EBUSY;
}
static void scc_exint(register struct scc_channel *scc);
static void scc_rxint(register struct scc_channel *scc);
static void scc_spint(register struct scc_channel *scc);
-static void scc_isr(int irq, struct pt_regs *regs);
+static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void scc_tx_timer(unsigned long);
static void scc_rx_timer(unsigned long);
static void scc_init_timer(struct scc_channel *scc);
*/
static void
-scc_isr(int irq, struct pt_regs *regs)
+scc_isr(int irq, void *dev_id, struct pt_regs *regs)
{
register unsigned char vector;
register struct scc_channel *scc;
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
{
- if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC"))
+ if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
printk("z8530drv: Warning --- could not get IRQ %d\n", hwcfg.irq);
else
Ivec[hwcfg.irq].used = 1;
}
for (k=0; k < 16 ; k++)
- if (Ivec[k].used) free_irq(k);
+ if (Ivec[k].used) free_irq(k, NULL);
restore_flags(flags);
}
* This is the serial driver's interrupt routine while we are probing
* for submarines.
*/
-static void rs_probe(int irq, struct pt_regs * regs)
+static void rs_probe(int irq, void *dev_id, struct pt_regs * regs)
{
rs_irq_triggered = irq;
rs_triggered |= 1 << irq;
/*
* This is the serial driver's generic interrupt routine
*/
-static void rs_interrupt(int irq, struct pt_regs * regs)
+static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
int status;
struct async_struct * info;
/*
* This is the serial driver's interrupt routine for a single port
*/
-static void rs_interrupt_single(int irq, struct pt_regs * regs)
+static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
{
int status;
int pass_counter = 0;
/*
* This is the serial driver's for multiport boards
*/
-static void rs_interrupt_multi(int irq, struct pt_regs * regs)
+static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs)
{
int status;
struct async_struct * info;
info = info->next_port;
} while (info);
if (rs_multiport[i].port1)
- rs_interrupt_multi(i, NULL);
+ rs_interrupt_multi(i, NULL, NULL);
else
- rs_interrupt(i, NULL);
+ rs_interrupt(i, NULL, NULL);
} else
- rs_interrupt_single(i, NULL);
+ rs_interrupt_single(i, NULL, NULL);
sti();
}
}
if (IRQ_ports[0]) {
cli();
- rs_interrupt(0, NULL);
+ rs_interrupt(0, NULL, NULL);
sti();
timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
int i, mask;
for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
- if (!(mask & dontgrab) && !request_irq(i, rs_probe, SA_INTERRUPT, "serial probe")) {
+ if (!(mask & dontgrab) && !request_irq(i, rs_probe, SA_INTERRUPT, "serial probe", NULL)) {
irq_lines |= mask;
}
}
for (i = 0; i < 16; i++) {
if (irq_lines & (1 << i))
- free_irq(i);
+ free_irq(i, NULL);
}
}
unsigned short ICP;
unsigned long flags;
int retval;
- void (*handler)(int, struct pt_regs *);
+ void (*handler)(int, void *, struct pt_regs *);
unsigned long page;
page = get_free_page(GFP_KERNEL);
if (info->irq && (!IRQ_ports[info->irq] ||
!IRQ_ports[info->irq]->next_port)) {
if (IRQ_ports[info->irq]) {
- free_irq(info->irq);
+ free_irq(info->irq, NULL);
if (rs_multiport[info->irq].port1)
handler = rs_interrupt_multi;
else
} else
handler = rs_interrupt_single;
- retval = request_irq(info->irq, handler, SA_INTERRUPT, "serial");
+ retval = request_irq(info->irq, handler, SA_INTERRUPT, "serial", NULL);
if (retval) {
restore_flags(flags);
if (suser()) {
if (info->irq && (!IRQ_ports[info->irq] ||
!IRQ_ports[info->irq]->next_port)) {
if (IRQ_ports[info->irq]) {
- free_irq(info->irq);
- retval = request_irq(info->irq, rs_interrupt_single, SA_INTERRUPT, "serial");
+ free_irq(info->irq, NULL);
+ retval = request_irq(info->irq, rs_interrupt_single, SA_INTERRUPT, "serial", NULL);
if (retval)
printk("serial shutdown: request_irq: error %d"
" Couldn't reacquire IRQ.\n", retval);
} else
- free_irq(info->irq);
+ free_irq(info->irq, NULL);
}
if (info->xmit_buf) {
struct rs_multiport_struct *multi;
int was_multi, now_multi;
int retval;
- void (*handler)(int, struct pt_regs *);
+ void (*handler)(int, void *, struct pt_regs *);
if (!suser())
return -EPERM;
if (IRQ_ports[info->irq]->next_port &&
(was_multi != now_multi)) {
- free_irq(info->irq);
+ free_irq(info->irq, NULL);
if (now_multi)
handler = rs_interrupt_multi;
else
handler = rs_interrupt;
retval = request_irq(info->irq, handler, SA_INTERRUPT,
- "serial");
+ "serial", NULL);
if (retval) {
printk("Couldn't reallocate serial interrupt "
"driver!!\n");
static void stl_sendbreak(stlport_t *portp, long len);
static int stl_waitcarrier(stlport_t *portp, struct file *filp);
static void stl_delay(int len);
-static void stl_intr(int irq, struct pt_regs *regs);
+static void stl_intr(int irq, void *dev_id, struct pt_regs *regs);
static void stl_offintr(void *private);
static void *stl_memalloc(int len);
}
for (i = 0; (i < stl_numintrs); i++)
- free_irq(stl_gotintrs[i]);
+ free_irq(stl_gotintrs[i], NULL);
restore_flags(flags);
}
* io region.
*/
-static void stl_intr(int irq, struct pt_regs *regs)
+static void stl_intr(int irq, void *dev_id, struct pt_regs *regs)
{
stlbrd_t *brdp;
stlpanel_t *panelp;
break;
}
if (i >= stl_numintrs) {
- if (request_irq(irq, stl_intr, SA_INTERRUPT, stl_drvname) != 0) {
+ if (request_irq(irq, stl_intr, SA_INTERRUPT, stl_drvname, NULL) != 0) {
printk("STALLION: failed to register interrupt routine for irq=%d\n", irq);
rc = -ENODEV;
} else {
* When we are finished, set flags to indicate end, disable timer.
* NOTE: This *must* be fast!
*/
-static void qic02_tape_interrupt(int irq, struct pt_regs *regs)
+static void qic02_tape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int stat, r, i;
static void qic02_release_resources(void)
{
- free_irq(QIC02_TAPE_IRQ);
+ free_irq(QIC02_TAPE_IRQ, NULL);
free_dma(QIC02_TAPE_DMA);
status_zombie = YES;
} /* qic02_release_resources */
*/
/* get IRQ */
- if (request_irq(QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02")) {
+ if (request_irq(QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02", NULL)) {
printk(TPQIC02_NAME ": can't allocate IRQ%d for QIC-02 tape\n",
QIC02_TAPE_IRQ);
status_zombie = YES;
if (request_dma(QIC02_TAPE_DMA,"QIC-02")) {
printk(TPQIC02_NAME ": can't allocate DMA%d for QIC-02 tape\n",
QIC02_TAPE_DMA);
- free_irq(QIC02_TAPE_IRQ);
+ free_irq(QIC02_TAPE_IRQ, NULL);
status_zombie = YES;
return -1;
}
if (register_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) {
printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", QIC02_TAPE_MAJOR);
#ifndef CONFIG_QIC02_DYNCONF
- free_irq(QIC02_TAPE_IRQ);
+ free_irq(QIC02_TAPE_IRQ, NULL);
free_dma(QIC02_TAPE_DMA);
#endif
return -ENODEV;
/* No drive detected, so vanish */
tpqputs(TPQD_ALWAYS, "No drive detected -- driver going on vacation...");
status_dead = YES;
- free_irq(QIC02_TAPE_IRQ);
+ free_irq(QIC02_TAPE_IRQ, NULL);
free_dma(QIC02_TAPE_DMA);
unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
return -ENODEV;
* Kernel methods.
*/
-static void wdt_interrupt(int irq, struct pt_regs *regs)
+static void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* Read the status register see what is up and
int init_module(void)
{
printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
- if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
+ if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
{
printk("IRQ %d is not free.\n", irq);
return -EIO;
mouse_deregister(&temp_mouse);
#endif
release_region(io,8);
- free_irq(irq);
+ free_irq(irq, NULL);
}
#else
int wdt_init(void)
{
printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
- if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p"))
+ if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
{
printk("IRQ %d is not free.\n", irq);
return -EIO;
readhscx_0(card->membase, 1, HSCX_VSTR) & 0xf);
}
} else {
+ switch (card->iobase) {
+ case 0x180:
+ case 0x280:
+ case 0x380:
+ printk(KERN_INFO "teles: port 0x%x specified, assuming 0x%x\n",
+ card->iobase, (card->iobase | 0xc00));
+ card->iobase |= 0xc00;
+ break;
+ }
if (check_region(card->iobase, 8)) {
printk(KERN_WARNING
"teles: ports %x-%x already in use\n",
#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/string.h>
-#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/config.h> /* for CONFIG_IP_MULTICAST */
static int el1_probe1(struct device *dev, int ioaddr);
static int el_open(struct device *dev);
static int el_start_xmit(struct sk_buff *skb, struct device *dev);
-static void el_interrupt(int irq, struct pt_regs *regs);
+static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el_receive(struct device *dev);
static void el_reset(struct device *dev);
static int el1_close(struct device *dev);
if (el_debug > 2)
printk("%s: Doing el_open()...", dev->name);
- if (request_irq(dev->irq, &el_interrupt, 0, "3c501"))
+ if (request_irq(dev->irq, &el_interrupt, 0, "3c501", NULL))
return -EAGAIN;
irq2dev_map[dev->irq] = dev;
* Handle the ether interface interrupts.
*/
-static void el_interrupt(int irq, struct pt_regs *regs)
+static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
* Free and disable the IRQ.
*/
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
outb(AX_RESET, AX_CMD); /* Reset the chip */
irq2dev_map[dev->irq] = 0;
Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards.
Paul Gortmaker : multiple card support for module users.
+ rjohnson@analogic.com : Fix up PIO interface for efficient operation.
*/
#include "8390.h"
#include "3c503.h"
-
+#define WRD_COUNT 4
int el2_probe(struct device *dev);
int el2_pio_probe(struct device *dev);
printk(version);
dev->base_addr = ioaddr;
-
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk ("3c503: unable to allocate memory for dev->priv.\n");
writel(test_val, mem_base + i);
if (readl(mem_base) != 0xba5eba5e
|| readl(mem_base + i) != test_val) {
- printk("3c503.c: memory failure or memory address conflict.\n");
+ printk("3c503: memory failure or memory address conflict.\n");
dev->mem_start = 0;
ei_status.name = "3c503-PIO";
break;
dev->mem_start, dev->mem_end-1);
else
+ {
+ ei_status.tx_start_page = EL2_MB1_START_PG;
+ ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
printk("\n%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
dev->name, ei_status.name, (wordlength+1)<<3);
-
+ }
return 0;
}
\f
outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */
do {
- if (request_irq (*irqp, NULL, 0, "bogus") != -EBUSY) {
+ if (request_irq (*irqp, NULL, 0, "bogus", NULL) != -EBUSY) {
/* Twinkle the interrupt, and check if it's seen. */
autoirq_setup(0);
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
outb_p(0x00, E33G_IDCFR);
if (*irqp == autoirq_report(0) /* It's a good IRQ line! */
- && request_irq (dev->irq = *irqp, &ei_interrupt, 0, ei_status.name) == 0)
+ && request_irq (dev->irq = *irqp, &ei_interrupt, 0, ei_status.name, NULL) == 0)
break;
}
} while (*++irqp);
return -EAGAIN;
}
} else {
- if (request_irq(dev->irq, &ei_interrupt, 0, ei_status.name)) {
+ if (request_irq(dev->irq, &ei_interrupt, 0, ei_status.name, NULL)) {
return -EAGAIN;
}
}
static int
el2_close(struct device *dev)
{
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
dev->irq = ei_status.saved_irq;
irq2dev_map[dev->irq] = NULL;
outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */
/* Set the interrupt line. */
outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
- outb_p(8, E33G_DRQCNT); /* Set burst size to 8 */
+ outb_p((WRD_COUNT << 1), E33G_DRQCNT); /* Set burst size to 8 */
outb_p(0x20, E33G_DMAAH); /* Put a valid addr in the GA DMA */
outb_p(0x00, E33G_DMAAL);
return; /* We always succeed */
}
-/* Either use the shared memory (if enabled on the board) or put the packet
- out through the ASIC FIFO. The latter is probably much slower. */
+/*
+ * Either use the shared memory (if enabled on the board) or put the packet
+ * out through the ASIC FIFO.
+ */
static void
el2_block_output(struct device *dev, int count,
const unsigned char *buf, const start_page)
{
- int i; /* Buffer index */
- int boguscount = 0; /* timeout counter */
+ unsigned short int *wrd;
+ int boguscount; /* timeout counter */
+ unsigned shor tmp_rev; /* temporary for reversed values */
if (ei_status.word16) /* Tx packets go into bank 0 on EL2/16 card */
outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */
return;
}
- /* No shared memory, put the packet out the slow way. */
- /* Set up then start the internal memory transfer to Tx Start Page */
- outb(0x00, E33G_DMAAL);
- outb_p(start_page, E33G_DMAAH);
+
+/*
+ * No shared memory, put the packet out the other way.
+ * Set up then start the internal memory transfer to Tx Start Page
+ */
+
+ tmp_rev = htons((unsigned short)start_page);
+ outb(tmp_rev&0xFF, E33G_DMAAH);
+ outb(tmp_rev>>8, E33G_DMAAL);
+
outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
| ECNTRL_START, E33G_CNTRL);
- /* This is the byte copy loop: it should probably be tuned for
- speed once everything is working. I think it is possible
- to output 8 bytes between each check of the status bit. */
- for(i = 0; i < count; i++) {
- if (i % 8 == 0)
- while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
- if (++boguscount > (i<<3) + 32) {
- printk("%s: FIFO blocked in el2_block_output (at %d of %d, bc=%d).\n",
- dev->name, i, count, boguscount);
- outb(EGACFR_NORM, E33G_GACFR); /* To MB1 for EL2/16 */
- return;
- }
- outb(buf[i], E33G_FIFOH);
+/*
+ * Here I am going to write data to the FIFO as quickly as possible.
+ * Note that E33G_FIFOH is defined incorrectly. It is really
+ * E33G_FIFOL, the lowest port address for both the byte and
+ * word write. Variable 'count' is NOT checked. Caller must supply a
+ * valid count. Note that I may write a harmless extra byte to the
+ * 8390 if the byte-count was not even.
+ */
+ wrd = (unsigned short int *) buf;
+ count = (count + 1) >> 1;
+ for(;;)
+ {
+ boguscount = 0x1000;
+ while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+ {
+ if(!boguscount--)
+ {
+ printk("%s: FIFO blocked in el2_block_output.\n", dev->name);
+ el2_reset_8390(dev);
+ goto blocked;
+ }
+ }
+ if(count > WRD_COUNT)
+ {
+ outsw(E33G_FIFOH, wrd, WRD_COUNT);
+ wrd += WRD_COUNT;
+ count -= WRD_COUNT;
+ }
+ else
+ {
+ outsw(E33G_FIFOH, wrd, count);
+ break;
+ }
}
+ blocked:;
outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
- outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */
return;
}
static void
el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
- unsigned int i;
+ int boguscount;
unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
- unsigned long fifo_watchdog;
+ unsigned short tmp_rev;
if (dev->mem_start) { /* Use the shared memory. */
-#ifdef notdef
- /* Officially this is what we are doing, but the readl() is faster */
memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-#else
- ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
return;
}
- /* No shared memory, use programmed I/O. Ugh. */
- outb(0, E33G_DMAAL);
- outb_p(ring_page & 0xff, E33G_DMAAH);
+/*
+ * No shared memory, use programmed I/O.
+ */
+
+ tmp_rev = htons((unsigned short)ring_page);
+ outb(tmp_rev&0xFF, E33G_DMAAH);
+ outb(tmp_rev>>8, E33G_DMAAL);
+
outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
| ECNTRL_START, E33G_CNTRL);
-
- /* Header is < 8 bytes, so only check the FIFO at the beginning. */
- fifo_watchdog = jiffies;
- while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) {
- if (jiffies - fifo_watchdog > 2*HZ/100) {
- printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
- break;
- }
+ boguscount = 0x1000;
+ while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+ {
+ if(!boguscount--)
+ {
+ printk("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
+ memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
+ el2_reset_8390(dev);
+ goto blocked;
+ }
}
-
- for(i = 0; i < sizeof(struct e8390_pkt_hdr); i++)
- ((char *)(hdr))[i] = inb_p(E33G_FIFOH);
-
+ insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);
+ blocked:;
outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
}
-/* Returns the new ring pointer. */
+
static void
el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
{
int boguscount = 0;
+ unsigned short int *buf;
+ unsigned short tmp_rev;
+
int end_of_ring = dev->rmem_end;
- unsigned int i;
/* Maybe enable shared memory just be to be safe... nahh.*/
if (dev->mem_start) { /* Use the shared memory. */
}
return;
}
- /* No shared memory, use programmed I/O. */
- outb(ring_offset & 0xff, E33G_DMAAL);
- outb_p((ring_offset >> 8) & 0xff, E33G_DMAAH);
+
+/*
+ * No shared memory, use programmed I/O.
+ */
+ tmp_rev = htons((unsigned short) ring_offset);
+ outb(tmp_rev&0xFF, E33G_DMAAL);
+ outb(tmp_rev>>8, E33G_DMAAH);
+
outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
| ECNTRL_START, E33G_CNTRL);
- /* This is the byte copy loop: it should probably be tuned for
- speed once everything is working. */
- for(i = 0; i < count; i++) {
- if (i % 8 == 0)
- while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
- if (++boguscount > (i<<3) + 32) {
- printk("%s: FIFO blocked in el2_block_input() (at %d of %d, bc=%d).\n",
- dev->name, i, count, boguscount);
- boguscount = 0;
- break;
- }
- (skb->data)[i] = inb_p(E33G_FIFOH);
+/*
+ * Here I also try to get data as fast as possible. I am betting that I
+ * can read one extra byte without clobering anything in the kernel because
+ * this would only occur on an odd byte-count and allocation of skb->data
+ * is word-aligned. Variable 'count' is NOT checked. Caller must check
+ * for a valid count.
+ * [This is currently quite safe.... but if one day the 3c503 explodes
+ * you know where to come looking ;)]
+ */
+
+ buf = (unsigned short int *) skb->data;
+ count = (count + 1) >> 1;
+ for(;;)
+ {
+ boguscount = 0x1000;
+ while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+ {
+ if(!boguscount--)
+ {
+ printk("%s: FIFO blocked in el2_block_input.\n", dev->name);
+ el2_reset_8390(dev);
+ goto blocked;
+ }
+ }
+ if(count > WRD_COUNT)
+ {
+ insw(E33G_FIFOH, buf, WRD_COUNT);
+ buf += WRD_COUNT;
+ count -= WRD_COUNT;
+ }
+ else
+ {
+ insw(E33G_FIFOH, buf, count);
+ break;
+ }
}
+ blocked:;
outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+ return;
}
-
-\f
#ifdef MODULE
#define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
+#define NAMELEN 8 /* #of chars for storing dev->name */
+
static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, };
static struct device dev_el2[MAX_EL2_CARDS] = {
{
}
found++;
}
-
return 0;
}
******************************************************/
static void
-elp_interrupt (int irq, struct pt_regs *reg_ptr)
+elp_interrupt (int irq, void *dev_id, struct pt_regs *reg_ptr)
{
int len;
int dlen;
/*
* install our interrupt service routine
*/
- if (request_irq(dev->irq, &elp_interrupt, 0, "3c505")) {
+ if (request_irq(dev->irq, &elp_interrupt, 0, "3c505", NULL)) {
irq2dev_map[dev->irq] = NULL;
return -EAGAIN;
}
/*
* release the IRQ
*/
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
/*
* and we no longer have to map irq to dev either
static int el16_probe1(struct device *dev, int ioaddr);
static int el16_open(struct device *dev);
static int el16_send_packet(struct sk_buff *skb, struct device *dev);
-static void el16_interrupt(int irq, struct pt_regs *regs);
+static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el16_rx(struct device *dev);
static int el16_close(struct device *dev);
static struct enet_statistics *el16_get_stats(struct device *dev);
irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
- irqval = request_irq(irq, &el16_interrupt, 0, "3c507");
+ irqval = request_irq(irq, &el16_interrupt, 0, "3c507", NULL);
if (irqval) {
printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval);
return EAGAIN;
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-el16_interrupt(int irq, struct pt_regs *regs)
+el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
dev_3c507.priv = NULL;
/* If we don't do this, we can't re-insmod it later. */
- free_irq(dev_3c507.irq);
+ free_irq(dev_3c507.irq, NULL);
release_region(dev_3c507.base_addr, EL16_IO_EXTENT);
}
#endif /* MODULE */
static ushort read_eeprom(short ioaddr, int index);
static int el3_open(struct device *dev);
static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
-static void el3_interrupt(int irq, struct pt_regs *regs);
+static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void update_stats(int addr, struct device *dev);
static struct enet_statistics *el3_get_stats(struct device *dev);
static int el3_rx(struct device *dev);
outw(RxReset, ioaddr + EL3_CMD);
outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
- if (request_irq(dev->irq, &el3_interrupt, 0, "3c509")) {
+ if (request_irq(dev->irq, &el3_interrupt, 0, "3c509", NULL)) {
return -EAGAIN;
}
/* The EL3 interrupt handler. */
static void
-el3_interrupt(int irq, struct pt_regs *regs)
+el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
int ioaddr, status;
outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
}
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
/* Switching back to window 0 disables the IRQ. */
EL3WINDOW(0);
/* But we explicitly zero the IRQ line select anyway. */
static void vortex_timer(unsigned long arg);
static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
static int vortex_rx(struct device *dev);
-static void vortex_interrupt(int irq, struct pt_regs *regs);
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct device *dev);
static void update_stats(int addr, struct device *dev);
static struct enet_statistics *vortex_get_stats(struct device *dev);
if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL)
return -EAGAIN;
irq2dev_map[dev->irq] = dev;
- if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
+ if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name, NULL)) {
irq2dev_map[dev->irq] = NULL;
return -EAGAIN;
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void vortex_interrupt(int irq, struct pt_regs *regs)
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
#ifdef USE_SHARED_IRQ
struct device *dev = (struct device *)(irq == 0 ? regs : irq2dev_map[irq]);
if (donedidthis++ > 1) {
printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
dev->name, status, dev->start);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
}
}
#ifdef USE_SHARED_IRQ
free_shared_irq(dev->irq, dev);
#else
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
/* Mmmm, we should diable all interrupt sources here. */
irq2dev_map[dev->irq] = 0;
#endif
\f
/* The typical workload of the driver:
Handle the ether interface interrupts. */
-void ei_interrupt(int irq, struct pt_regs * regs)
+void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
int e8390_base;
extern void NS8390_init(struct device *dev, int startp);
extern int ei_open(struct device *dev);
extern int ei_close(struct device *dev);
-extern void ei_interrupt(int irq, struct pt_regs *regs);
+extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
#ifndef HAVE_AUTOIRQ
/* From auto_irq.c */
else if (dev->irq == 2)
dev->irq = 9;
- if (request_irq(dev->irq, ei_interrupt, 0, "ac3200")) {
+ if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", NULL)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return EAGAIN;
}
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to allocate memory for dev->priv.\n");
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -ENOMEM;
}
/* Someday we may enable the IRQ and shared memory here. */
int ioaddr = dev->base_addr;
- if (request_irq(dev->irq, ei_interrupt, 0, "ac3200"))
+ if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", NULL))
return -EAGAIN;
#endif
#ifdef notyet
/* We should someday disable shared memory and interrupts. */
outb(0x00, ioaddr + 6); /* Disable interrupts. */
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
#endif
kfree(dev->priv);
dev->priv = NULL;
/* Someday free_irq + irq2dev may be in ac_close_card() */
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
release_region(dev->base_addr, AC_IO_EXTENT);
unregister_netdev(dev);
static int i596_open(struct device *dev);
static int i596_start_xmit(struct sk_buff *skb, struct device *dev);
-static void i596_interrupt(int irq, struct pt_regs *regs);
+static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int i596_close(struct device *dev);
static struct enet_statistics *i596_get_stats(struct device *dev);
static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
if (i596_debug > 1)
printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
- if (request_irq(dev->irq, &i596_interrupt, 0, "apricot"))
+ if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", NULL))
return -EAGAIN;
irq2dev_map[dev->irq] = dev;
if (i < 4)
{
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
return -EAGAIN;
}
}
static void
-i596_interrupt(int irq, struct pt_regs *regs)
+i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct i596_private *lp;
dev->name, lp->scb.status, lp->scb.command);
break;
}
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
remove_rx_bufs(dev);
MOD_DEC_USE_COUNT;
char *data,int length,int daddr,int exceptA);
static int arcnet_go_tx(struct device *dev,int enable_irq);
-static void arcnet_interrupt(int irq,struct pt_regs *regs);
+static void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
static void arcnet_inthandler(struct device *dev);
static void arcnet_rx(struct device *dev,int recbuf);
dev->base_addr=port;
/* reserve the irq */
- irqval = request_irq(airq,&arcnet_interrupt,0,"arcnet");
+ irqval = request_irq(airq,&arcnet_interrupt,0,"arcnet",NULL);
if (irqval)
{
BUGMSG(D_NORMAL,"unable to get IRQ %d (irqval=%d).\n",
* as well.
*/
static void
-arcnet_interrupt(int irq,struct pt_regs *regs)
+arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
int ioaddr;
if (thiscard.irq)
{
- free_irq(thiscard.irq);
+ free_irq(thiscard.irq,NULL);
/* very important! */
irq2dev_map[thiscard.irq] = NULL;
}
static int read_eeprom(int ioaddr, int location);
static int net_open(struct device *dev);
static int net_send_packet(struct sk_buff *skb, struct device *dev);
-static void net_interrupt(int irq, struct pt_regs *regs);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct device *dev);
static int net_close(struct device *dev);
static struct enet_statistics *net_get_stats(struct device *dev);
| (read_eeprom(ioaddr, 0)>>14)];
/* Snarf the interrupt vector now. */
- if (request_irq(irq, &net_interrupt, 0, "at1700")) {
+ if (request_irq(irq, &net_interrupt, 0, "at1700", NULL)) {
printk ("AT1700 found at %#3x, but it's unusable due to a conflict on"
"IRQ %d.\n", ioaddr, irq);
return EAGAIN;
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-net_interrupt(int irq, struct pt_regs *regs)
+net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
dev_at1700.priv = NULL;
/* If we don't do this, we can't re-insmod it later. */
- free_irq(dev_at1700.irq);
+ free_irq(dev_at1700.irq, NULL);
irq2dev_map[dev_at1700.irq] = NULL;
release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
}
static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
static void trigger_send(short ioaddr, int length);
static int net_send_packet(struct sk_buff *skb, struct device *dev);
-static void net_interrupt(int irq, struct pt_regs *regs);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct device *dev);
static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
static int net_close(struct device *dev);
port or interrupt may be shared. */
if (irq2dev_map[dev->irq] != 0
|| (irq2dev_map[dev->irq] = dev) == 0
- || request_irq(dev->irq, &net_interrupt, 0, "ATP")) {
+ || request_irq(dev->irq, &net_interrupt, 0, "ATP", NULL)) {
return -EAGAIN;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-net_interrupt(int irq, struct pt_regs * regs)
+net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
/* Free the IRQ line. */
outb(0x00, ioaddr + PAR_CONTROL);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
/* Leave the hardware in a reset state. */
static unsigned long irq_handled; /* The irq lines we have a handler on. */
static volatile int irq_number; /* The latest irq number we actually found. */
-static void autoirq_probe(int irq, struct pt_regs * regs)
+static void autoirq_probe(int irq, void *dev_id, struct pt_regs * regs)
{
irq_number = irq;
set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */
irq_handled = 0;
for (i = 0; i < 16; i++) {
if (test_bit(i, &irqs_busy) == 0
- && request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe") == 0)
+ && request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe", NULL) == 0)
set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/
}
/* Update our USED lists. */
#ifdef notdef
printk(" Spurious interrupt on IRQ %d\n", i);
#endif
- free_irq(i);
+ free_irq(i, NULL);
}
}
return irq_handled;
/* Retract the irq handlers that we installed. */
for (i = 0; i < 16; i++) {
if (test_bit(i, (void *)&irq_handled))
- free_irq(i);
+ free_irq(i, NULL);
}
return irq_number;
}
*/
static int de4x5_open(struct device *dev);
static int de4x5_queue_pkt(struct sk_buff *skb, struct device *dev);
-static void de4x5_interrupt(int irq, struct pt_regs *regs);
+static void de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int de4x5_close(struct device *dev);
static struct enet_statistics *de4x5_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev);
dce_ms_delay(10);
}
- if (request_irq(dev->irq, (void *)de4x5_interrupt, 0, lp->adapter_name)) {
+ if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, lp->adapter_name, dev)) {
printk("de4x5_open(): Requested IRQ%d is busy\n",dev->irq);
status = -EAGAIN;
} else {
** interrupt is asserted and this routine entered.
*/
static void
-de4x5_interrupt(int irq, struct pt_regs *regs)
+de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct device *dev = (struct device *)(irq2dev_map[irq]);
+ struct device *dev = (struct device *)dev_id;
struct de4x5_private *lp;
s32 imr, omr, sts;
u_long iobase;
/*
** Free the associated irq
*/
- free_irq(dev->irq);
+ free_irq(dev->irq, dev);
irq2dev_map[dev->irq] = 0;
MOD_DEC_USE_COUNT;
static int de600_start_xmit(struct sk_buff *skb, struct device *dev);
/* Dispatch from interrupts. */
-static void de600_interrupt(int irq, struct pt_regs *regs);
+static void de600_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int de600_tx_intr(struct device *dev, int irq_status);
static void de600_rx_intr(struct device *dev);
static int
de600_open(struct device *dev)
{
- if (request_irq(DE600_IRQ, de600_interrupt, 0, "de600")) {
+ if (request_irq(DE600_IRQ, de600_interrupt, 0, "de600", NULL)) {
printk ("%s: unable to get IRQ %d\n", dev->name, DE600_IRQ);
return 1;
}
select_prn();
if (dev->start) {
- free_irq(DE600_IRQ);
+ free_irq(DE600_IRQ, NULL);
irq2dev_map[DE600_IRQ] = NULL;
dev->start = 0;
MOD_DEC_USE_COUNT;
* Handle the network interface interrupts.
*/
static void
-de600_interrupt(int irq, struct pt_regs * regs)
+de600_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = irq2dev_map[irq];
byte irq_status;
static int de620_start_xmit(struct sk_buff *, struct device *);
/* Dispatch from interrupts. */
-static void de620_interrupt(int, struct pt_regs *);
+static void de620_interrupt(int, void *, struct pt_regs *);
static int de620_rx_intr(struct device *);
/* Initialization */
static int
de620_open(struct device *dev)
{
- if (request_irq(dev->irq, de620_interrupt, 0, "de620")) {
+ if (request_irq(dev->irq, de620_interrupt, 0, "de620", NULL)) {
printk ("%s: unable to get IRQ %d\n", dev->name, dev->irq);
return 1;
}
/* disable recv */
de620_set_register(dev, W_TCR, RXOFF);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
dev->start = 0;
*
*/
static void
-de620_interrupt(int irq_in, struct pt_regs *regs)
+de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
{
struct device *dev = irq2dev_map[irq_in];
byte irq_status;
*/
static int depca_open(struct device *dev);
static int depca_start_xmit(struct sk_buff *skb, struct device *dev);
-static void depca_interrupt(int irq, struct pt_regs * regs);
+static void depca_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static int depca_close(struct device *dev);
static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd);
static struct enet_statistics *depca_get_stats(struct device *dev);
depca_dbg_open(dev);
- if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name)) {
+ if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, NULL)) {
printk("depca_open(): Requested IRQ%d is busy\n",dev->irq);
status = -EAGAIN;
} else {
** The DEPCA interrupt handler.
*/
static void
-depca_interrupt(int irq, struct pt_regs * regs)
+depca_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct depca_private *lp;
/*
** Free the associated irq
*/
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
MOD_DEC_USE_COUNT;
if (dev->irq < 2) {
int irqlist[] = {15,11,10,12,5,9,3,4}, i;
for (i = 0; i < 8; i++)
- if (request_irq (irqlist[i], NULL, 0, "bogus") != -EBUSY) {
+ if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
dev->irq = irqlist[i];
break;
}
{
short ioaddr = dev->base_addr;
- if (request_irq(dev->irq, ei_interrupt, 0, "e2100")) {
+ if (request_irq(dev->irq, ei_interrupt, 0, "e2100", NULL)) {
return EBUSY;
}
irq2dev_map[dev->irq] = dev;
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
dev->irq = ei_status.saved_irq;
/* Shut off the interrupt line and secondary interface. */
static int eepro_probe1(struct device *dev, short ioaddr);
static int eepro_open(struct device *dev);
static int eepro_send_packet(struct sk_buff *skb, struct device *dev);
-static void eepro_interrupt(int irq, struct pt_regs *regs);
+static void eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void eepro_rx(struct device *dev);
static void eepro_transmit_interrupt(struct device *dev);
static int eepro_close(struct device *dev);
if (dev->irq > 2) {
printk(", IRQ %d, %s.\n", dev->irq,
ifmap[dev->if_port]);
- if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro")) {
+ if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", NULL)) {
printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
return -EAGAIN;
}
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
- if (request_irq (*irqp, NULL, 0, "bogus") != EBUSY) {
+ if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) {
/* Twinkle the interrupt, and check if it's seen */
autoirq_setup(0);
outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
if (*irqp == autoirq_report(2) && /* It's a good IRQ line */
- (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro") == 0))
+ (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", NULL) == 0))
break;
/* clear all interrupts */
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-eepro_interrupt(int irq, struct pt_regs * regs)
+eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
int ioaddr, status, boguscount = 0;
outb(RESET_CMD, ioaddr);
/* release the interrupt */
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
static int eexp_probe1(struct device *dev, short ioaddr);
static int eexp_open(struct device *dev);
static int eexp_send_packet(struct sk_buff *skb, struct device *dev);
-static void eexp_interrupt(int irq, struct pt_regs *regs);
+static void eexp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void eexp_rx(struct device *dev);
static int eexp_close(struct device *dev);
static struct enet_statistics *eexp_get_stats(struct device *dev);
if (irq2dev_map[dev->irq] != 0
/* This is always true, but avoid the false IRQ. */
|| (irq2dev_map[dev->irq] = dev) == 0
- || request_irq(dev->irq, &eexp_interrupt, 0, "EExpress")) {
+ || request_irq(dev->irq, &eexp_interrupt, 0, "EExpress", NULL)) {
return -EAGAIN;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-eexp_interrupt(int irq, struct pt_regs *regs)
+eexp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
/* Disable the physical interrupt line. */
outb(0, ioaddr + SET_IRQ);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
static int eth16i_close(struct device *dev);
static int eth16i_tx(struct sk_buff *skb, struct device *dev);
static void eth16i_rx(struct device *dev);
-static void eth16i_interrupt(int irq, struct pt_regs *regs);
+static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs);
static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
static void eth16i_initialize(struct device *dev);
dev->irq = irq;
/* Try to obtain interrupt vector */
- if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i")) {
+ if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i", NULL)) {
printk("%s: %s at %#3x, but is unusable due
conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
return EAGAIN;
return;
}
-static void eth16i_interrupt(int irq, struct pt_regs *regs)
+static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct eth16i_local *lp;
void cleanup_module(void)
{
unregister_netdev( &dev_eth16i );
- free_irq( dev_eth16i.irq );
+ free_irq( dev_eth16i.irq, NULL );
irq2dev_map[ dev_eth16i.irq ] = NULL;
release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
}
Added verify_area() calls in depca_ioctl() from
suggestion by <heiko@colossus.escape.de>.
Add new multicasting code.
+ 0.41 20-Jan-96 Fix IRQ set up problem reported by <???>.
=========================================================================
*/
-static const char *version = "ewrk3.c:v0.40 95/12/27 davies@wanton.lkg.dec.com\n";
+static const char *version = "ewrk3.c:v0.41 96/1/20 davies@wanton.lkg.dec.com\n";
#include <linux/module.h>
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
-#define QUEUE_PKT_TIMEOUT (100) /* Jiffies */
+#define QUEUE_PKT_TIMEOUT (1*HZ) /* Jiffies */
/*
** EtherWORKS 3 shared memory window sizes
*/
static int ewrk3_open(struct device *dev);
static int ewrk3_queue_pkt(struct sk_buff *skb, struct device *dev);
-static void ewrk3_interrupt(int irq, struct pt_regs *regs);
+static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int ewrk3_close(struct device *dev);
static struct enet_statistics *ewrk3_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev);
nicsr = inb(EWRK3_CSR);
icr = inb(EWRK3_ICR);
- icr |= 0xf0;
+ icr &= 0x70;
outb(icr, EWRK3_ICR); /* Disable all the IRQs */
if (nicsr == CSR_TXD|CSR_RXD) {
if (!lp->hard_strapped) {
irq2dev_map[dev->irq] = dev; /* For latched interrupts */
- if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3")) {
+ if (request_irq(dev->irq, (void *)ewrk3_interrupt, 0, "ewrk3", NULL)) {
printk("ewrk3_open(): Requested IRQ%d is busy\n",dev->irq);
status = -EAGAIN;
} else {
for (i=0; i<skb->len; i++) {
outb(*p++, EWRK3_DATA);
}
- outb(page, EWRK3_TQ); /* Start sending pkt */
+ outb(page, EWRK3_TQ); /* Start sending pkt */
} else {
writeb((char)(TCR_QMODE|TCR_PAD|TCR_IFC), (char *)buf);/* ctrl byte*/
buf+=1;
if (lp->txc) {
writeb((char)(((skb->len >> 8) & 0xff) | XCT), (char *)buf);
buf+=1;
- writeb(0x04, (char *)buf); /* index byte */
+ writeb(0x04, (char *)buf); /* index byte */
buf+=1;
- writeb(0x00, (char *)(buf + skb->len)); /* Write the XCT flag */
+ writeb(0x00, (char *)(buf + skb->len)); /* Write the XCT flag */
memcpy_toio(buf, skb->data, PRELOAD);/* Write PRELOAD bytes*/
- outb(page, EWRK3_TQ); /* Start sending pkt */
+ outb(page, EWRK3_TQ); /* Start sending pkt */
memcpy_toio(buf+PRELOAD, skb->data+PRELOAD, skb->len-PRELOAD);
- writeb(0xff, (char *)(buf + skb->len)); /* Write the XCT flag */
+ writeb(0xff, (char *)(buf + skb->len)); /* Write the XCT flag */
} else {
writeb((char)((skb->len >> 8) & 0xff), (char *)buf);
buf+=1;
- writeb(0x04, (char *)buf); /* index byte */
+ writeb(0x04, (char *)buf); /* index byte */
buf+=1;
memcpy_toio((char *)buf, skb->data, skb->len);/* Write data bytes */
- outb(page, EWRK3_TQ); /* Start sending pkt */
+ outb(page, EWRK3_TQ); /* Start sending pkt */
}
}
** The EWRK3 interrupt handler.
*/
static void
-ewrk3_interrupt(int irq, struct pt_regs * regs)
+ewrk3_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct ewrk3_private *lp;
while (inb(EWRK3_RQ));
if (!lp->hard_strapped) {
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
}
void
cleanup_module(void)
{
- release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);
-
if (thisEthwrk.priv) {
kfree(thisEthwrk.priv);
thisEthwrk.priv = NULL;
thisEthwrk.irq = 0;
unregister_netdev(&thisEthwrk);
+ release_region(thisEthwrk.base_addr, EWRK3_TOTAL_SIZE);
}
#endif /* MODULE */
int ioaddr = dev->base_addr - NIC_OFFSET;
int option_reg;
- if (request_irq(dev->irq, &ei_interrupt, 0, "hp-plus")) {
+ if (request_irq(dev->irq, &ei_interrupt, 0, "hp-plus", NULL)) {
return -EAGAIN;
}
int ioaddr = dev->base_addr - NIC_OFFSET;
int option_reg = inw(ioaddr + HPP_OPTION);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
ei_close(dev);
outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
int *irqp = wordmode ? irq_16list : irq_8list;
do {
int irq = *irqp;
- if (request_irq (irq, NULL, 0, "bogus") != -EBUSY) {
+ if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
autoirq_setup(0);
/* Twinkle the interrupt, and check if it's seen. */
outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
if (irq == autoirq_report(0) /* It's a good IRQ line! */
- && request_irq (irq, &ei_interrupt, 0, "hp") == 0) {
+ && request_irq (irq, &ei_interrupt, 0, "hp", NULL) == 0) {
printk(" selecting IRQ %d.\n", irq);
dev->irq = *irqp;
break;
} else {
if (dev->irq == 2)
dev->irq = 9;
- if (request_irq(dev->irq, ei_interrupt, 0, "hp")) {
+ if (request_irq(dev->irq, ei_interrupt, 0, "hp", NULL)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return EBUSY;
}
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to get memory for dev->priv.\n");
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -ENOMEM;
}
int ioaddr = dev->base_addr - NIC_OFFSET;
kfree(dev->priv);
dev->priv = NULL;
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
release_region(ioaddr, HP_IO_EXTENT);
unregister_netdev(dev);
static void hp100_update_stats( struct device *dev );
static void hp100_clear_stats( int ioaddr );
static void hp100_set_multicast_list( struct device *dev);
-static void hp100_interrupt( int irq, struct pt_regs *regs );
+static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs );
static void hp100_start_interface( struct device *dev );
static void hp100_stop_interface( struct device *dev );
int ioaddr = dev -> base_addr;
struct hp100_private *lp = (struct hp100_private *)dev -> priv;
- if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name ) )
+ if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name, NULL ) )
{
printk( "%s: unable to get IRQ %d\n", dev -> name, dev -> irq );
return -EAGAIN;
dev -> tbusy = 1;
dev -> start = 0;
- free_irq( dev -> irq );
+ free_irq( dev -> irq, NULL );
irq2dev_map[ dev -> irq ] = NULL;
MOD_DEC_USE_COUNT;
return 0;
* hardware interrupt handling
*/
-static void hp100_interrupt( int irq, struct pt_regs *regs )
+static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs )
{
struct device *dev = (struct device *)irq2dev_map[ irq ];
struct hp100_private *lp;
unsigned char get_sram_size(struct tok_info *adapt_info);
static void tok_init_card(unsigned long dev_addr);
-static void tok_interrupt(int irq, struct pt_regs *regs);
+static void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void initial_tok_int(struct device *dev);
DPRINTK("Using %dK shared RAM\n",ti->mapped_ram_size/2);
#endif
- if (request_irq (dev->irq = irq, &tok_interrupt,0,"IBM TR") != 0) {
+ if (request_irq (dev->irq = irq, &tok_interrupt,0,"IBM TR", NULL) != 0) {
DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",irq);
badti = ti; /* keep track of unused tok_info */
return ENODEV;
return 0;
}
-static void tok_interrupt (int irq, struct pt_regs *regs)
+static void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char status;
unregister_netdev(&dev_ibmtr);
/* If we don't do this, we can't re-insmod it later. */
- free_irq(dev_ibmtr.irq);
+ free_irq(dev_ibmtr.irq, NULL);
irq2dev_map[dev_ibmtr.irq] = NULL;
release_region(dev_ibmtr.base_addr, TR_IO_EXTENT);
}
static void lance_init_ring(struct device *dev);
static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
static int lance_rx(struct device *dev);
-static void lance_interrupt(int irq, struct pt_regs *regs);
+static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int lance_close(struct device *dev);
static struct enet_statistics *lance_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev);
int i;
if (dev->irq == 0 ||
- request_irq(dev->irq, &lance_interrupt, 0, lp->name)) {
+ request_irq(dev->irq, &lance_interrupt, 0, lp->name, NULL)) {
return -EAGAIN;
}
/* The LANCE interrupt handler. */
static void
-lance_interrupt(int irq, struct pt_regs * regs)
+lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct lance_private *lp;
if (dev->dma != 4)
disable_dma(dev->dma);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
{
- int irqval = request_irq(dev->irq, ei_interrupt, 0, name);
+ int irqval = request_irq(dev->irq, ei_interrupt, 0, name, NULL);
if (irqval) {
printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
return EAGAIN;
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to get memory for dev->priv.\n");
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -ENOMEM;
}
if (dev->priv != NULL) {
kfree(dev->priv);
dev->priv = NULL;
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
release_region(dev->base_addr, NE_IO_EXTENT);
unregister_netdev(dev);
#define NI52_ADDR2 0x01
static int ni52_probe1(struct device *dev,int ioaddr);
-static void ni52_interrupt(int irq,struct pt_regs *reg_ptr);
+static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
static int ni52_open(struct device *dev);
static int ni52_close(struct device *dev);
static int ni52_send_packet(struct sk_buff *,struct device *);
*/
static int ni52_close(struct device *dev)
{
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
ni_reset586(); /* the hard way to stop the receiver */
startrecv586(dev);
ni_enaint();
- if(request_irq(dev->irq, &ni52_interrupt,0,"ni5210"))
+ if(request_irq(dev->irq, &ni52_interrupt,0,"ni5210",NULL))
{
ni_reset586();
return -EAGAIN;
* Interrupt Handler ...
*/
-static void ni52_interrupt(int irq,struct pt_regs *reg_ptr)
+static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
{
struct device *dev = (struct device *) irq2dev_map[irq];
unsigned short stat;
#define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
static int ni65_probe1(struct device **dev,int);
-static void ni65_interrupt(int irq, struct pt_regs *regs);
+static void ni65_interrupt(int irq, void * dev_id, struct pt_regs *regs);
static void ni65_recv_intr(struct device *dev,int);
static void ni65_xmit_intr(struct device *dev,int);
static int ni65_open(struct device *dev);
"ni6510", dev->base_addr, dev->irq,dev->dma);
{
- int irqval = request_irq(dev->irq, &ni65_interrupt,0,"ni6510");
+ int irqval = request_irq(dev->irq, &ni65_interrupt,0,"ni6510",NULL);
if (irqval) {
printk ("%s: unable to get IRQ %d (irqval=%d).\n",
dev->name,dev->irq, irqval);
if(request_dma(dev->dma, "ni6510") != 0)
{
printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
- free_irq(dev->irq);
+ free_irq(dev->irq,NULL);
return -EAGAIN;
}
}
printk(KERN_ERR "%s: can't RESET ni6510 card: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
disable_dma(dev->dma);
free_dma(dev->dma);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return 0;
}
printk(KERN_ERR "%s: can't init am7990/lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
disable_dma(dev->dma);
free_dma(dev->dma);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return 0; /* false */
}
/*
* interrupt handler
*/
-static void ni65_interrupt(int irq, struct pt_regs * regs)
+static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
{
int csr0;
struct device *dev = (struct device *) irq2dev_map[irq];
static int pi_probe(struct device *dev, int card_type);
static int pi_open(struct device *dev);
static int pi_send_packet(struct sk_buff *skb, struct device *dev);
-static void pi_interrupt(int reg_ptr, struct pt_regs *regs);
+static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs);
static int pi_close(struct device *dev);
static int pi_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
static struct enet_statistics *pi_get_stats(struct device *dev);
now. There is no point in waiting since no other device can use
the interrupt, and this marks the 'irqaction' as busy. */
{
- int irqval = request_irq(dev->irq, &pi_interrupt,0, "pi2");
+ int irqval = request_irq(dev->irq, &pi_interrupt,0, "pi2", NULL);
if (irqval) {
printk("PI: unable to get IRQ %d (irqval=%d).\n",
dev->irq, irqval);
if (dev->base_addr & 2) { /* if A channel */
if (first_time) {
if (request_dma(dev->dma,"pi2")) {
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -EAGAIN;
}
irq2dev_map[dev->irq] = dev;
/* The typical workload of the driver:
Handle the network interface interrupts. */
-static void pi_interrupt(int reg_ptr, struct pt_regs *regs)
+static void pi_interrupt(int reg_ptr, void *dev_id, struct pt_regs *regs)
{
/* int irq = -(((struct pt_regs *) reg_ptr)->orig_eax + 2);*/
struct pi_local *lp;
static void plip_bh(struct device *dev);
/* Interrupt handler */
-static void plip_interrupt(int irq, struct pt_regs *regs);
+static void plip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/* Functions for DEV methods */
static int plip_rebuild_header(void *buff, struct device *dev,
\f
/* Handle the parallel port interrupts. */
static void
-plip_interrupt(int irq, struct pt_regs * regs)
+plip_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *) irq2dev_map[irq];
struct net_local *nl = (struct net_local *)dev->priv;
return -EAGAIN;
}
cli();
- if (request_irq(dev->irq , plip_interrupt, 0, dev->name) != 0) {
+ if (request_irq(dev->irq , plip_interrupt, 0, dev->name, NULL) != 0) {
sti();
printk("%s: couldn't get IRQ %d.\n", dev->name, dev->irq);
return -EAGAIN;
dev->tbusy = 1;
dev->start = 0;
cli();
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
nl->is_deferred = 0;
nl->connection = PLIP_CN_NONE;
static int pt_probe(struct device *dev);
static int pt_open(struct device *dev);
static int pt_send_packet(struct sk_buff *skb, struct device *dev);
-static void pt_interrupt(int irq, struct pt_regs *regs);
+static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int pt_close(struct device *dev);
static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
static struct enet_statistics *pt_get_stats(struct device *dev);
* the interrupt, and this marks the 'irqaction' as busy.
*/
{
- int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt");
+ int irqval = request_irq(dev->irq, &pt_interrupt,0, "pt", NULL);
if (irqval) {
printk("PT: ERROR: Unable to get IRQ %d (irqval = %d).\n",
dev->irq, irqval);
{
if (request_dma(dev->dma, "pt"))
{
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -EAGAIN;
}
}
* This routine is called by the kernel when there is an interrupt for the
* PT.
*/
-static void pt_interrupt(int irq, struct pt_regs *regs)
+static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/* It's a tad dodgy here, but we assume pt0a until proven otherwise */
struct device *dev = &pt0a;
static int seeq8005_probe1(struct device *dev, int ioaddr);
static int seeq8005_open(struct device *dev);
static int seeq8005_send_packet(struct sk_buff *skb, struct device *dev);
-static void seeq8005_interrupt(int irq, struct pt_regs *regs);
+static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void seeq8005_rx(struct device *dev);
static int seeq8005_close(struct device *dev);
static struct enet_statistics *seeq8005_get_stats(struct device *dev);
#if 0
{
- int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005");
+ int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", NULL);
if (irqval) {
printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
dev->irq, irqval);
struct net_local *lp = (struct net_local *)dev->priv;
{
- int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005");
+ int irqval = request_irq(dev->irq, &seeq8005_interrupt, 0, "seeq8005", NULL);
if (irqval) {
printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
dev->irq, irqval);
/* The typical workload of the driver:
Handle the network interface interrupts. */
static void
-seeq8005_interrupt(int irq, struct pt_regs * regs)
+seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
/* Flush the Tx and disable Rx here. */
outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/malloc.h>
-#include <linux/ioport.h>
#include <linux/string.h>
#include <asm/system.h>
#include <asm/io.h>
static int SK_open(struct device *dev);
static int SK_send_packet(struct sk_buff *skb, struct device *dev);
-static void SK_interrupt(int irq, struct pt_regs * regs);
+static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
static void SK_rxintr(struct device *dev);
static void SK_txintr(struct device *dev);
static int SK_close(struct device *dev);
do
{
- irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16");
+ irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16", NULL);
i++;
} while (irqval && irqtab[i]);
}
else if (dev->irq == 2) /* IRQ2 is always IRQ9 */
{
- if (request_irq(9, &SK_interrupt, 0, "sk_g16"))
+ if (request_irq(9, &SK_interrupt, 0, "sk_g16", NULL))
{
printk("%s: unable to get IRQ 9\n", dev->name);
return -EAGAIN;
/* check if IRQ free and valid. Then install Interrupt handler */
- if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16"))
+ if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16", NULL))
{
printk("%s: unable to get selected IRQ\n", dev->name);
return -EAGAIN;
* Description : SK_G16 interrupt handler which checks for LANCE
* Errors, handles transmit and receive interrupts
*
- * Parameters : I : int irq, struct pt_regs * regs -
+ * Parameters : I : int irq, void *dev_id, struct pt_regs * regs -
* Return Value : None
* Errors : None
* Globals : None
* YY/MM/DD uid Description
-*/
-static void SK_interrupt(int irq, struct pt_regs * regs)
+static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
int csr0;
struct device *dev = (struct device *) irq2dev_map[irq];
SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */
- free_irq(dev->irq); /* Free IRQ */
+ free_irq(dev->irq, NULL); /* Free IRQ */
irq2dev_map[dev->irq] = 0; /* Mark IRQ as unused */
return 0; /* always succeed */
static int netcard_probe1(struct device *dev, int ioaddr);
static int net_open(struct device *dev);
static int net_send_packet(struct sk_buff *skb, struct device *dev);
-static void net_interrupt(int irq, struct pt_regs *regs);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct device *dev);
static int net_close(struct device *dev);
static struct enet_statistics *net_get_stats(struct device *dev);
dev->irq = 9;
{
- int irqval = request_irq(dev->irq, &net_interrupt, 0, cardname);
+ int irqval = request_irq(dev->irq, &net_interrupt, 0, cardname, NULL);
if (irqval) {
printk("%s: unable to get IRQ %d (irqval=%d).\n",
dev->name, dev->irq, irqval);
* This is used if the interrupt line can turned off (shared).
* See 3c503.c for an example of selecting the IRQ at config-time.
*/
- if (request_irq(dev->irq, &net_interrupt, 0, cardname)) {
+ if (request_irq(dev->irq, &net_interrupt, 0, cardname, NULL)) {
return -EAGAIN;
}
/*
* and clean up on failure.
*/
if (request_dma(dev->dma, cardname)) {
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -EAGAIN;
}
irq2dev_map[dev->irq] = dev;
* Handle the network interface interrupts.
*/
static void
-net_interrupt(int irq, struct pt_regs * regs)
+net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct net_local *lp;
/* If not IRQ or DMA jumpered, free up the line. */
outw(0x00, ioaddr+0); /* Release the physical interrupt line. */
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
free_dma(dev->dma);
irq2dev_map[dev->irq] = 0;
* allocate them in net_probe1().
*/
/*
- free_irq(this_device.irq);
+ free_irq(this_device.irq, NULL);
free_dma(this_device.dma);
*/
release_region(this_device.base_addr, NETCARD_IO_EXTENT);
{
for (i = 0; i < slip_maxdev; i++)
{
- if (slip_ctrls[i]->dev.start)
- /* VSV = if dev->start==0, then device
- unregistred while close proc. */
+ if (slip_ctrls[i])
{
- unregister_netdev(&(slip_ctrls[i]->dev));
+ /*
+ * VSV = if dev->start==0, then device
+ * unregistred while close proc.
+ */
+ if (slip_ctrls[i]->dev.start)
+ unregister_netdev(&(slip_ctrls[i]->dev));
+
kfree(slip_ctrls[i]);
+ slip_ctrls[i] = NULL;
}
}
kfree(slip_ctrls);
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
- if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name))
+ if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, NULL))
return -EAGAIN;
outb(ULTRA_MEMENB, ioaddr); /* Enable memory, 16 bit mode. */
printk("%s: Shutting down ethercard.\n", dev->name);
outb(0x00, ioaddr + 6); /* Disable interrupts. */
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
NS8390_init(dev, 0);
}
static void
-lance_interrupt (int irq, struct pt_regs *regs)
+lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *) (irq2dev_map [irq]);
struct lance_private *lp;
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- if (request_irq (dev->irq, &lance_interrupt, 0, "LANCE")){
+ if (request_irq (dev->irq, &lance_interrupt, 0, "LANCE", NULL)){
printk ("Lance: Can't get irq %d\n", dev->irq);
return -EAGAIN;
}
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
- free_irq (dev->irq);
+ free_irq (dev->irq, NULL);
irq2dev_map [dev->irq] = NULL;
return 0;
static void tulip_init_ring(struct device *dev);
static int tulip_start_xmit(struct sk_buff *skb, struct device *dev);
static int tulip_rx(struct device *dev);
-static void tulip_interrupt(int irq, struct pt_regs *regs);
+static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int tulip_close(struct device *dev);
static struct enet_statistics *tulip_get_stats(struct device *dev);
static void set_multicast_list(struct device *dev);
if (irq2dev_map[dev->irq] != NULL
|| (irq2dev_map[dev->irq] = dev) == NULL
|| dev->irq == 0
- || request_irq(dev->irq, &tulip_interrupt, 0, "DEC 21040 Tulip")) {
+ || request_irq(dev->irq, &tulip_interrupt, 0, "DEC 21040 Tulip", NULL)) {
return -EAGAIN;
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void tulip_interrupt(int irq, struct pt_regs *regs)
+static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)(irq2dev_map[irq]);
struct tulip_private *lp;
if (dev->start == 0 && --stopit < 0) {
printk("%s: Emergency stop, looping startup interrupt.\n",
dev->name);
- free_irq(irq);
+ free_irq(irq, NULL);
}
}
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = 0;
MOD_DEC_USE_COUNT;
static int wavelan_probe1(device *, unsigned short);
static int wavelan_open(device *);
static int wavelan_send_packet(struct sk_buff *, device *);
-static void wavelan_interrupt(int, struct pt_regs *);
+static void wavelan_interrupt(int, void *, struct pt_regs *);
static int wavelan_close(device *);
static en_stats *wavelan_get_stats(device *);
static void wavelan_set_multicast_list(device *);
||
(irq2dev_map[dev->irq] = dev) == (device *)0
||
- request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN") != 0
+ request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", NULL) != 0
)
{
irq2dev_map[dev->irq] = (device *)0;
if (r == -1)
{
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = (device *)0;
if (wavelan_debug > 0)
printk("%s: <-wavelan_open(): -EAGAIN(2)\n", dev->name);
static
void
-wavelan_interrupt(int irq, struct pt_regs *regs)
+wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
device *dev;
unsigned short ioaddr;
wavelan_ints_off(dev);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = (device *)0;
/*
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
- if (request_irq(dev->irq, ei_interrupt, 0, model_name)) {
+ if (request_irq(dev->irq, ei_interrupt, 0, model_name, NULL)) {
printk (" unable to get IRQ %d.\n", dev->irq);
return EAGAIN;
}
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to get memory for dev->priv.\n");
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
return -ENOMEM;
}
int ioaddr = dev->base_addr - WD_NIC_OFFSET;
kfree(dev->priv);
dev->priv = NULL;
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
irq2dev_map[dev->irq] = NULL;
release_region(ioaddr, WD_IO_EXTENT);
unregister_netdev(dev);
int znet_probe(struct device *dev);
static int znet_open(struct device *dev);
static int znet_send_packet(struct sk_buff *skb, struct device *dev);
-static void znet_interrupt(int irq, struct pt_regs *regs);
+static void znet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void znet_rx(struct device *dev);
static int znet_close(struct device *dev);
static struct enet_statistics *net_get_stats(struct device *dev);
zn.tx_dma = netinfo->dma2;
/* These should never fail. You can't add devices to a sealed box! */
- if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet")
+ if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", NULL)
|| request_dma(zn.rx_dma,"ZNet rx")
|| request_dma(zn.tx_dma,"ZNet tx")) {
printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name);
}
/* The ZNET interrupt handler. */
-static void znet_interrupt(int irq, struct pt_regs * regs)
+static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = irq2dev_map[irq];
int ioaddr;
disable_dma(zn.rx_dma);
disable_dma(zn.tx_dma);
- free_irq(dev->irq);
+ free_irq(dev->irq, NULL);
if (znet_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
static int NCR53c8xx_run_tests (struct Scsi_Host *host);
static int NCR53c8xx_script_len;
static int NCR53c8xx_dsa_len;
-static void NCR53c7x0_intr(int irq, struct pt_regs * regs);
+static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
static int ncr_halt (struct Scsi_Host *host);
static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd
*cmd);
search->irq == host->irq && search != host); search=search->next);
if (!search) {
- if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx")) {
+ if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7,8xx", NULL)) {
printk("scsi%d : IRQ%d not free, detaching\n"
" You have either a configuration problem, or a\n"
" broken BIOS. You may wish to manually assign\n"
}
/*
- * Function : static void NCR53c7x0_intr (int irq, struct pt_regs * regs)
+ * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
*
* Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
* the same IRQ line.
*/
static void
-NCR53c7x0_intr (int irq, struct pt_regs * regs) {
+NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
NCR53c7x0_local_declare();
struct Scsi_Host *host; /* Host we are looking at */
unsigned char istat; /* Values of interrupt regs */
(hostdata->chip / 100 == 8 ? ISTAT_800_INTF : 0))) {
printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no,
cmd->pid);
- NCR53c7x0_intr (host->irq, NULL);
+ NCR53c7x0_intr (host->irq, NULL, NULL);
return SCSI_ABORT_BUSY;
}
if (tmp->hostt == the_template && tmp->irq == host->irq)
++irq_count;
if (irq_count == 1)
- free_irq(host->irq);
+ free_irq(host->irq, NULL);
}
if (host->dma_channel != DMA_NONE)
free_dma(host->dma_channel);
static __inline__ void initialize_SCp(Scsi_Cmnd *cmd);
static __inline__ void run_main(void);
static void AM53C974_main (void);
-static void AM53C974_intr(int irq, struct pt_regs *regs);
+static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs);
static void AM53C974_intr_disconnect(struct Scsi_Host *instance);
static int AM53C974_sync_neg(struct Scsi_Host *instance, int target, unsigned char *msg);
static __inline__ void AM53C974_set_async(struct Scsi_Host *instance, int target);
(search->irq != instance->irq) || (search == instance) );
search = search->next);
if (!search) {
- if (request_irq(instance->irq, AM53C974_intr, SA_INTERRUPT, "AM53C974")) {
+ if (request_irq(instance->irq, AM53C974_intr, SA_INTERRUPT, "AM53C974", NULL)) {
printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq);
scsi_unregister(instance);
return -1; }
main_running = 0;
}
-/*********************************************************************
-* Function : AM53C974_intr(int irq, struct pt_regs *regs) *
-* *
-* Purpose : interrupt handler *
-* *
-* Inputs : irq - interrupt line, regs - ? *
-* *
-* Returns : nothing *
-**********************************************************************/
-static void AM53C974_intr(int irq, struct pt_regs *regs)
+/************************************************************************
+* Function : AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs) *
+* *
+* Purpose : interrupt handler *
+* *
+* Inputs : irq - interrupt line, regs - ? *
+* *
+* Returns : nothing *
+************************************************************************/
+static void AM53C974_intr(int irq, void *dev_id, struct pt_regs *regs)
{
AM53C974_local_declare();
struct Scsi_Host *instance;
if (BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]++ == 0)
{
if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
- SA_INTERRUPT, HostAdapter->InterruptLabel) < 0)
+ SA_INTERRUPT, HostAdapter->InterruptLabel, NULL) < 0)
{
BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]--;
printk("scsi%d: UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
*/
if (HostAdapter->IRQ_ChannelAcquired)
if (--BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9] == 0)
- free_irq(HostAdapter->IRQ_Channel);
+ free_irq(HostAdapter->IRQ_Channel, NULL);
/*
Release exclusive access to the DMA Channel.
*/
static int probe_irq;
-static void probe_intr (int irq, struct pt_regs * regs) {
+static void probe_intr (int irq, void *dev_id, struct pt_regs * regs) {
probe_irq = irq;
};
NCR5380_setup(instance);
for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
- if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe")
+ if ((mask & possible) && (request_irq(i, &probe_intr, SA_INTERRUPT, "NCR-probe", NULL)
== 0))
trying_irqs |= mask;
for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)
if (trying_irqs & mask)
- free_irq(i);
+ free_irq(i, NULL);
return probe_irq;
}
*
*/
-static void NCR5380_intr (int irq, struct pt_regs * regs) {
+static void NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs) {
NCR5380_local_declare();
struct Scsi_Host *instance;
int done;
#endif
static void NCR5380_init (struct Scsi_Host *instance, int flags);
static void NCR5380_information_transfer (struct Scsi_Host *instance);
-static void NCR5380_intr (int irq, struct pt_regs * regs);
+static void NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs);
static void NCR5380_main (void);
static void NCR5380_print_options (struct Scsi_Host *instance);
static void NCR5380_print_phase (struct Scsi_Host *instance);
};
/* Static function prototypes */
-static void NCR53c406a_intr(int, struct pt_regs *);
+static void NCR53c406a_intr(int, void *, struct pt_regs *);
static void internal_done(Scsi_Cmnd *);
static void wait_intr(void);
static void chip_init(void);
request_region(port_base, 0x10, "NCR53c406a");
if(irq_level > 0) {
- if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a")){
+ if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a", NULL)){
printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level);
return 0;
}
return;
}
- NCR53c406a_intr(0, NULL);
+ NCR53c406a_intr(0, NULL, NULL);
}
int NCR53c406a_command(Scsi_Cmnd *SCpnt){
}
static void
-NCR53c406a_intr(int unused, struct pt_regs *regs){
+NCR53c406a_intr(int unused, void *dev_id, struct pt_regs *regs){
DEB(unsigned char fifo_size;)
DEB(unsigned char seq_reg;)
unsigned char status, int_reg;
#ifdef LINUX_1_3
STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
#endif /* LINUX_1_3 */
-STATIC void advansys_interrupt(int, struct pt_regs *);
+STATIC void advansys_interrupt(int, void *, struct pt_regs *);
STATIC void advansys_command_done(Scsi_Cmnd *);
STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
/* Register IRQ Number. */
ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
if ((ret = request_irq(shp->irq, advansys_interrupt,
- SA_INTERRUPT, "advansys")) != 0) {
+ SA_INTERRUPT, "advansys", NULL)) != 0) {
ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
release_region(shp->io_port, shp->n_io_port);
if (shp->dma_channel != NO_ISA_DMA) {
if (shp->dma_channel != NO_ISA_DMA) {
free_dma(shp->dma_channel);
}
- free_irq(shp->irq);
+ free_irq(shp->irq, NULL);
scsi_unregister(shp);
asc_board_count--;
continue;
advansys_release(struct Scsi_Host *shp)
{
ASC_DBG(1, "advansys_release: begin\n");
- free_irq(shp->irq);
+ free_irq(shp->irq, NULL);
if (shp->dma_channel != NO_ISA_DMA) {
ASC_DBG(1, "advansys_release: free_dma()\n");
free_dma(shp->dma_channel);
* First-level interrupt handler.
*/
STATIC void
-advansys_interrupt(int irq, struct pt_regs *regs)
+advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
int flags;
#endif
};
-void aha152x_intr(int irq, struct pt_regs *);
+void aha152x_intr(int irq, void *dev_id, struct pt_regs *);
void aha152x_done(struct Scsi_Host *shpnt, int error);
void aha152x_setup(char *str, int *ints);
int aha152x_checksetup(struct aha152x_setup *setup);
SETBITS(DMACNTRL0, INTEN);
- ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x");
+ ok = request_irq(setup[i].irq, aha152x_intr, SA_INTERRUPT, "aha152x", NULL);
if(ok<0)
{
/*
* Interrupts handler (main routine of the driver)
*/
-void aha152x_intr(int irqno, struct pt_regs * regs)
+void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
{
struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
unsigned int flags;
}
/* A "high" level interrupt handler */
-static void aha1542_intr_handle(int irq, struct pt_regs *regs)
+static void aha1542_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
void (*my_done)(Scsi_Cmnd *) = NULL;
int errstatus, mbi, mbo, mbistatus;
DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
save_flags(flags);
cli();
- if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542")) {
+ if (request_irq(irq_level,aha1542_intr_handle, 0, "aha1542", NULL)) {
printk("Unable to allocate IRQ for adaptec controller.\n");
goto unregister;
}
if (dma_chan != 0xFF) {
if (request_dma(dma_chan,"aha1542")) {
printk("Unable to allocate DMA channel for Adaptec.\n");
- free_irq(irq_level);
+ free_irq(irq_level, NULL);
goto unregister;
}
}
/* A "high" level interrupt handler */
-void aha1740_intr_handle(int irq, struct pt_regs * regs)
+void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
{
void (*my_done)(Scsi_Cmnd *);
int errstatus, adapstat;
DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level));
- if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740"))
+ if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740", NULL))
{
printk("Unable to allocate IRQ for adaptec controller.\n");
return 0;
* be disabled all through this function unless we say otherwise.
*-F*************************************************************************/
static void
-aic7xxx_isr(int irq, struct pt_regs * regs)
+aic7xxx_isr(int irq, void *dev_id, struct pt_regs * regs)
{
int base, intstat;
struct aic7xxx_host *p;
/*
* Register IRQ with the kernel.
*/
- if (request_irq(config->irq, aic7xxx_isr, SA_INTERRUPT, "aic7xxx"))
+ if (request_irq(config->irq, aic7xxx_isr, SA_INTERRUPT, "aic7xxx", NULL))
{
printk("aic7xxx: Couldn't register IRQ %d, ignoring.\n", config->irq);
aic7xxx_boards[config->irq] = NULL;
#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
#define BN(board) (HD(board)->board_name)
-static void eata2x_interrupt_handler(int, struct pt_regs *);
+static void eata2x_interrupt_handler(int, void *, struct pt_regs *);
static int do_trace = FALSE;
static inline unchar wait_on_busy(ushort iobase) {
/* Board detected, allocate its IRQ if not already done */
if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq
- (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name))) {
+ (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
return FALSE;
}
if (subversion == ISA && request_dma(dma_channel, driver_name)) {
printk("%s: unable to allocate DMA channel %u, detaching.\n",
name, dma_channel);
- free_irq(irq);
+ free_irq(irq, NULL);
return FALSE;
}
if (sh[j] == NULL) {
printk("%s: unable to register host, detaching.\n", name);
- if (irqlist[irq] == NO_IRQ) free_irq(irq);
+ if (irqlist[irq] == NO_IRQ) free_irq(irq, NULL);
if (subversion == ISA) free_dma(dma_channel);
}
}
-static void eata2x_interrupt_handler(int irq, struct pt_regs * regs) {
+static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) {
Scsi_Cmnd *SCpnt;
unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
struct mssp *spp;
return;
}
-void eata_fake_int_handler(s32 irq, struct pt_regs * regs)
+void eata_fake_int_handler(s32 irq, void *dev_id, struct pt_regs * regs)
{
fake_int_result = inb((ulong)fake_int_base + HA_RSTATUS);
fake_int_happened = TRUE;
int eata_release(struct Scsi_Host *sh)
{
uint i;
- if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
+ if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL);
else reg_IRQ[sh->irq]--;
scsi_init_free((void *)status, 512);
#endif
-void eata_int_handler(int irq, struct pt_regs * regs)
+void eata_int_handler(int irq, void *dev_id, struct pt_regs * regs)
{
uint i, result = 0;
uint hba_stat, scsi_stat, eata_stat;
if (reg_IRQ[gc->IRQ] == FALSE) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, (void *) eata_fake_int_handler, SA_INTERRUPT,
- "eata_dma")){
+ "eata_dma", NULL)){
reg_IRQ[gc->IRQ]++;
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
dma_channel, base);
reg_IRQ[gc->IRQ]--;
if (reg_IRQ[gc->IRQ] == 0)
- free_irq(gc->IRQ);
+ free_irq(gc->IRQ, NULL);
if (gc->IRQ_TR == FALSE)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
free_dma(dma_channel);
reg_IRQ[gc->IRQ]--;
if (reg_IRQ[gc->IRQ] == 0)
- free_irq(gc->IRQ);
+ free_irq(gc->IRQ, NULL);
if (gc->IRQ_TR == FALSE)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
reg_IRQ[gc->IRQ]--;
if (reg_IRQ[gc->IRQ] == 0)
- free_irq(gc->IRQ);
+ free_irq(gc->IRQ, NULL);
if (gc->IRQ_TR == FALSE)
reg_IRQL[gc->IRQ] = FALSE;
return (FALSE);
for (i = 0; i <= MAXIRQ; i++) { /* Now that we know what we have, we */
if (reg_IRQ[i]){ /* exchange the interrupt handler which */
- free_irq(i); /* we used for probing with the real one */
- request_irq(i, (void *)(eata_int_handler), SA_INTERRUPT, "eata_dma");
+ free_irq(i, NULL); /* we used for probing with the real one */
+ request_irq(i, (void *)(eata_int_handler), SA_INTERRUPT, "eata_dma", NULL);
}
}
HBA_ptr = first_HBA;
#ifdef MODULE
int eata_pio_release(struct Scsi_Host *sh)
{
- if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq);
+ if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL);
else reg_IRQ[sh->irq]--;
if (SD(sh)->channel == 0) {
if (sh->io_port && sh->n_io_port)
}
}
-void eata_pio_int_handler(int irq, struct pt_regs * regs)
+void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs)
{
uint eata_stat = 0xfffff;
Scsi_Cmnd *cmd;
if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */
if (!request_irq(gc->IRQ, eata_pio_int_handler, SA_INTERRUPT,
- "EATA-PIO")){
+ "EATA-PIO", NULL)){
reg_IRQ[gc->IRQ]++;
if (!gc->IRQ_TR)
reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */
for (i = 0; i <= MAXIRQ; i++)
if (reg_IRQ[i])
- request_irq(i, eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO");
+ request_irq(i, eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL);
HBA_ptr = first_HBA;
static int FIFO_Size = 0x2000; /* 8k FIFO for
pre-tmc18c30 chips */
-extern void fdomain_16x0_intr( int irq, struct pt_regs * regs );
+extern void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs );
static void *addresses[] = {
(void *)0xc8000,
/* Register the IRQ with the kernel */
retcode = request_irq( interrupt_level,
- fdomain_16x0_intr, SA_INTERRUPT, "fdomain" );
+ fdomain_16x0_intr, SA_INTERRUPT, "fdomain", NULL);
if (retcode < 0) {
if (retcode == -EINVAL) {
#endif
}
-void fdomain_16x0_intr( int irq, struct pt_regs * regs )
+void fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
{
int status;
int done = 0;
instance->irq = NCR5380_probe_irq(instance, 0xffff);
if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380")) {
+ if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
NCR5380_setup(instance);
- free_irq(instance->irq);
+ free_irq(instance->irq, NULL);
return 0;
}
ficmsk = 0;}
}
-static void in2000_intr_handle(int irq, struct pt_regs *regs)
+static void in2000_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
int result=0;
unsigned int count,auxstatus,scsistatus,cmdphase,scsibyte;
"\n",base, irq_level);
outb(2,ININTR); /* Shut off the FIFO first, so it won't ask for data.*/
- if (request_irq(irq_level,in2000_intr_handle, 0, "in2000"))
+ if (request_irq(irq_level,in2000_intr_handle, 0, "in2000", NULL))
{
printk("in2000_detect: Unable to allocate IRQ.\n");
return 0;
instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, pas16_intr, SA_INTERRUPT, "pas16")) {
+ if (request_irq(instance->irq, pas16_intr, SA_INTERRUPT, "pas16", NULL)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
#if QL_USE_IRQ
/*----------------------------------------------------------------*/
/* interrupt handler */
-static void ql_ihandl(int irq, struct pt_regs * regs)
+static void ql_ihandl(int irq, void *dev_id, struct pt_regs * regs)
{
Scsi_Cmnd *icmd;
REG0;
else
printk( "Ql: Using preset IRQ %d\n", qlirq );
- if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
+ if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic", NULL))
host->can_queue = 1;
#endif
request_region( qbase , 0x10 ,"qlogic");
{"TEXEL","CD-ROM","1.06", BLIST_BORKEN},
{"INSITE","Floptical F*8I","*", BLIST_KEY},
{"INSITE","I325VM","*", BLIST_KEY},
-{"PIONEER","CD-ROMDRM-602X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
-{"PIONEER","CD-ROMDRM-604X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
+{"PIONEER","CD-ROM DRM-602X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
+{"PIONEER","CD-ROM DRM-604X","*", BLIST_FORCELUN | BLIST_SINGLELUN},
/*
* Must be at end of list...
*/
struct Scsi_Host * host = NULL;
for(j=0;j<SDpnt->host->cmd_per_lun;j++){
- SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
- SCpnt->host = SDpnt->host;
+ host = SDpnt->host;
+ SCpnt = (Scsi_Cmnd *)
+ scsi_init_malloc(sizeof(Scsi_Cmnd),
+ GFP_ATOMIC |
+ (host->unchecked_isa_dma ? GFP_DMA : 0));
+ SCpnt->host = host;
SCpnt->device = SDpnt;
SCpnt->target = SDpnt->id;
SCpnt->lun = SDpnt->lun;
SCpnt->underflow = 0;
SCpnt->transfersize = 0;
SCpnt->host_scribble = NULL;
- host = SDpnt->host;
if(host->host_queue)
host->host_queue->prev = SCpnt;
SCpnt->next = host->host_queue;
* It should do the right thing for most correctly
* written host adapters.
*/
- if (shpnt->irq) free_irq(shpnt->irq);
+ if (shpnt->irq) free_irq(shpnt->irq, NULL);
if (shpnt->dma_channel != 0xff) free_dma(shpnt->dma_channel);
if (shpnt->io_port && shpnt->n_io_port)
release_region(shpnt->io_port, shpnt->n_io_port);
put_user(sd[MINOR(inode->i_rdev)].nr_sects,
(long *) arg);
return 0;
+
case BLKRASET:
- if(!suser()) return -EACCES;
+ if (!suser())
+ return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
return 0;
+
+ case BLKRAGET:
+ if (!arg)
+ return -EINVAL;
+ error = verify_area(VERIFY_WRITE, (int *) arg, sizeof(int));
+ if (error)
+ return error;
+ put_user(read_ahead[MAJOR(inode->i_rdev)], (int *) arg);
+ return 0;
+
case BLKFLSBUF:
if(!suser()) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
*/
static int hostno = -1;
-static void seagate_reconnect_intr(int, struct pt_regs *);
+static void seagate_reconnect_intr(int, void *, struct pt_regs *);
#ifdef FAST
static int fast = 1;
instance = scsi_register(tpnt, 0);
hostno = instance->host_no;
if (request_irq((int) irq, seagate_reconnect_intr, SA_INTERRUPT,
- (controller_type == SEAGATE) ? "seagate" : "tmc-8xx")) {
+ (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) {
printk("scsi%d : unable to allocate IRQ%d\n",
hostno, (int) irq);
return 0;
* asserting SEL.
*/
-static void seagate_reconnect_intr(int irq, struct pt_regs * regs)
+static void seagate_reconnect_intr(int irq, void *dev_id, struct pt_regs *regs)
{
int temp;
Scsi_Cmnd * SCtmp;
instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128")) {
+ if (request_irq(instance->irq, t128_intr, SA_INTERRUPT, "t128", NULL)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
#define BN(board) (HD(board)->board_name)
-static void u14_34f_interrupt_handler(int, struct pt_regs *);
+static void u14_34f_interrupt_handler(int, void *, struct pt_regs *);
static int do_trace = FALSE;
static inline unchar wait_on_busy(ushort iobase) {
/* Board detected, allocate its IRQ if not already done */
if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq
- (irq, u14_34f_interrupt_handler, SA_INTERRUPT, driver_name))) {
+ (irq, u14_34f_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
return FALSE;
}
if (subversion == ISA && request_dma(dma_channel, driver_name)) {
printk("%s: unable to allocate DMA channel %u, detaching.\n",
name, dma_channel);
- free_irq(irq);
+ free_irq(irq, NULL);
return FALSE;
}
if (sh[j] == NULL) {
printk("%s: unable to register host, detaching.\n", name);
- if (irqlist[irq] == NO_IRQ) free_irq(irq);
+ if (irqlist[irq] == NO_IRQ) free_irq(irq, NULL);
if (subversion == ISA) free_dma(dma_channel);
return 0;
}
-static void u14_34f_interrupt_handler(int irq, struct pt_regs * regs) {
+static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) {
Scsi_Cmnd *SCpnt;
unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
struct mscp *spp;
};
#endif
-static void ultrastor_interrupt(int, struct pt_regs *);
+static void ultrastor_interrupt(int, void *, struct pt_regs *);
static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt);
config.mscp_free = ~0;
#endif
- if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor")) {
+ if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor", NULL)) {
printk("Unable to allocate IRQ%u for UltraStor controller.\n",
config.interrupt);
return FALSE;
if (config.dma_channel && request_dma(config.dma_channel,"Ultrastor")) {
printk("Unable to allocate DMA channel %u for UltraStor controller.\n",
config.dma_channel);
- free_irq(config.interrupt);
+ free_irq(config.interrupt, NULL);
return FALSE;
}
tpnt->sg_tablesize = ULTRASTOR_14F_MAX_SG;
printk("U24F: invalid IRQ\n");
return FALSE;
}
- if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor"))
+ if (request_irq(config.interrupt, ultrastor_interrupt, 0, "Ultrastor", NULL))
{
printk("Unable to allocate IRQ%u for UltraStor controller.\n",
config.interrupt);
return 0;
}
-static void ultrastor_interrupt(int irq, struct pt_regs *regs)
+static void ultrastor_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int status;
#if ULTRASTOR_MAX_CMDS > 1
#define wd7000_intr_ack(host) outb(0,host->iobase+ASC_INTR_ACK)
-void wd7000_intr_handle(int irq, struct pt_regs * regs)
+void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs * regs)
{
register int flag, icmb, errstatus, icmb_status;
register int host_error, scsi_error;
}
WAIT(host->iobase+ASC_STAT, ASC_STATMASK, ASC_INIT, 0);
- if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000")) {
+ if (request_irq(host->irq, wd7000_intr_handle, SA_INTERRUPT, "wd7000", NULL)) {
printk("wd7000_init: can't get IRQ %d.\n", host->irq);
return 0;
}
if (request_dma(host->dma,"wd7000")) {
printk("wd7000_init: can't get DMA channel %d.\n", host->dma);
- free_irq(host->irq);
+ free_irq(host->irq, NULL);
return 0;
}
wd7000_enable_dma(host);
if (!wd7000_diagnostics(host,ICB_DIAG_FULL)) {
free_dma(host->dma);
- free_irq(host->irq);
+ free_irq(host->irq, NULL);
return 0;
}
if (inb(host->iobase+ASC_STAT) & INT_IM) {
printk("wd7000_abort: lost interrupt\n");
- wd7000_intr_handle(host->irq, NULL);
+ wd7000_intr_handle(host->irq, NULL, NULL);
return SCSI_ABORT_SUCCESS;
}
*/
#include <linux/config.h>
-
-#define DEB(x)
-#define DEB1(x)
#include "sound_config.h"
#if defined(CONFIG_AD1848)
unsigned long flags;
ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
- DEB (printk ("ad1848_close(void)\n"));
+ DDB (printk ("ad1848_close(void)\n"));
save_flags (flags);
cli ();
if (!share_dma)
{
if (sound_alloc_dma (dma_playback, "Sound System"))
- printk ("ad1848.c: Can't allocate DMA%d\n", dma_playback);
+ printk ("ad1848.c: Can't allocate DMA%d for playback\n",
+ dma_playback);
- if (dma_capture != dma_playback)
+ if (dma_capture != dma_playback && dma_capture != -1)
if (sound_alloc_dma (dma_capture, "Sound System (capture)"))
- printk ("ad1848.c: Can't allocate DMA%d\n", dma_capture);
+ printk ("ad1848.c: Can't allocate DMA%d for capture\n",
+ dma_capture);
}
/*
}
void
-ad1848_interrupt (int irq, struct pt_regs *dummy)
+ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char status;
ad1848_info *devc;
#endif
#ifdef CONFIG_MSS
-# ifndef PSEUDO_MSS
+ /* always define full MSS even for DEC Alphas, just in case... */
{SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
-# else
+# ifdef __alpha__
+ /* MSS without IRQ/DMA config registers (for DEC Alphas) */
{SNDCARD_PSEUDO_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
# endif
# ifdef MSS2_BASE
#include "gus_hw.h"
-void gusintr (int irq, struct pt_regs *dummy);
+void gusintr (int irq, void *dev_id, struct pt_regs *dummy);
int gus_base, gus_irq, gus_dma;
extern int gus_wave_volume;
}
void
-gusintr (int irq, struct pt_regs *dummy)
+gusintr (int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char src;
extern int gus_timer_enabled;
#ifdef CONFIG_GUSMAX
if (have_gus_max)
- ad1848_interrupt (irq, NULL);
+ ad1848_interrupt (irq, NULL, NULL);
#endif
while (1)
gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
- gusintr (0, NULL); /* Serve pending interrupts */
+ gusintr (0, NULL, NULL); /* Serve pending interrupts */
restore_flags (flags);
}
}
void
-mad16_sbintr (int irq, struct pt_regs *dummy)
+mad16_sbintr (int irq, void *dev_id, struct pt_regs *dummy)
{
int status;
}
void
-mauiintr (int irq, struct pt_regs *dummy)
+mauiintr (int irq, void *dev_id, struct pt_regs *dummy)
{
irq_ok = 1;
}
}
void
-mpuintr (int irq, struct pt_regs *dummy)
+mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
{
struct mpu_config *devc;
int dev;
/******************* Begin of the Interrupt Handler ********************/
void
-pasintr (int irq, struct pt_regs *dummy)
+pasintr (int irq, void *dev_id, struct pt_regs *dummy)
{
int status;
}
void
-sbmidiintr (int irq, struct pt_regs *dummy)
+sbmidiintr (int irq, void *dev_id, struct pt_regs *dummy)
{
if (input_avail ())
sb16midi_input_loop ();
}
void
-sbintr (int irq, struct pt_regs *dummy)
+sbintr (int irq, void *dev_id, struct pt_regs *dummy)
{
int status;
void request_sound_timer (int count);
void sound_stop_timer(void);
int snd_ioctl_return(int *addr, int value);
-int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *), char *name, int *osp);
+int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, void *, struct pt_regs *), char *name, int *osp);
void snd_release_irq(int vect);
void sound_dma_malloc(int dev);
void sound_dma_free(int dev);
long attach_sb16midi(long mem_start, struct address_info * hw_config);
int probe_sb16midi(struct address_info *hw_config);
void sb_midi_interrupt(int dummy);
-void sbmidiintr(int irq, struct pt_regs * dummy);
+void sbmidiintr(int irq, void *dev_id, struct pt_regs * dummy);
/* From sb_midi.c */
void sb_midi_init(int model);
long attach_gus_card(long mem_start, struct address_info * hw_config);
int probe_gus(struct address_info *hw_config);
int gus_set_midi_irq(int num);
-void gusintr(int irq, struct pt_regs * dummy);
+void gusintr(int irq, void *dev_id, struct pt_regs * dummy);
long attach_gus_db16(long mem_start, struct address_info * hw_config);
int probe_gus_db16(struct address_info *hw_config);
/* From mpu401.c */
long attach_mpu401(long mem_start, struct address_info * hw_config);
int probe_mpu401(struct address_info *hw_config);
-void mpuintr(int irq, struct pt_regs * dummy);
+void mpuintr(int irq, void *dev_id, struct pt_regs * dummy);
/* From uart6850.c */
long attach_uart6850(long mem_start, struct address_info * hw_config);
#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
-void ad1848_interrupt (int irq, struct pt_regs * dummy);
+void ad1848_interrupt (int irq, void *dev_id, struct pt_regs * dummy);
long attach_ms_sound(long mem_start, struct address_info * hw_config);
int probe_ms_sound(struct address_info *hw_config);
long attach_pnp_ad1848(long mem_start, struct address_info * hw_config);
}
int
-snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, struct pt_regs *), char *name, int *osp)
+snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, void *, struct pt_regs *), char *name, int *osp)
{
int retcode;
- retcode = request_irq (interrupt_level, hndlr, 0 /* SA_INTERRUPT */ , name);
+ retcode = request_irq (interrupt_level, hndlr, 0 /* SA_INTERRUPT */ , name, NULL);
if (retcode < 0)
{
printk ("Sound: IRQ%d already in use\n", interrupt_level);
snd_release_irq (int vect)
{
irqs &= ~(1ul << vect);
- free_irq (vect);
+ free_irq (vect, NULL);
}
int
}
void
-sscapeintr (int irq, struct pt_regs *dummy)
+sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char bits, tmp;
static int debug = 0;
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if (bits & 0x01)
{
- mpuintr (irq, NULL);
+ mpuintr (irq, NULL, NULL);
if (debug++ > 10) /* Temporary debugging hack */
{
sscape_write (devc, GA_INTENA_REG, 0x00); /* Disable all interrupts */
}
void
-m6850intr (int irq, struct pt_regs *dummy)
+m6850intr (int irq, void *dev_id, struct pt_regs *dummy)
{
if (input_avail ())
uart6850_input_loop ();
ntohs(sender.sipx_port),
packet_buf[0], packet_buf[1]);
- ncp_trigger_message(sk->protinfo.ipx.ncp_server);
+ ncp_trigger_message(sk->protinfo.af_ipx.ncp_server);
set_fs(fs);
}
}
sk->data_ready = ncp_msg_data_ready;
- sk->protinfo.ipx.ncp_server = server;
+ sk->protinfo.af_ipx.ncp_server = server;
return 0;
}
--- /dev/null
+#ifndef __ALPHA_ALCOR__H__
+#define __ALPHA_ALCOR__H__
+
+#include <linux/types.h>
+
+/*
+ * ALCOR is the internal name for the 2117x chipset which provides
+ * memory controller and PCI access for the 21164 chip based systems.
+ *
+ * This file is based on:
+ *
+ * DECchip 21171 Core Logic Chipset
+ * Technical Reference Manual
+ *
+ * EC-QE18B-TE
+ *
+ * david.rusling@reo.mts.dec.com Initial Version.
+ *
+ */
+
+/*------------------------------------------------------------------------**
+** **
+** EB164 I/O procedures **
+** **
+** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers **
+** inportbxt: 8 bits only **
+** inport: alias of inportw **
+** outport: alias of outportw **
+** **
+** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers **
+** inmembxt: 8 bits only **
+** inmem: alias of inmemw **
+** outmem: alias of outmemw **
+** **
+**------------------------------------------------------------------------*/
+
+
+/* ALCOR ADDRESS BIT DEFINITIONS
+ *
+ * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | \_/ \_/
+ * | | |
+ * +-- IO space, not cached. Byte Enable --+ |
+ * Transfer Length --+
+ *
+ *
+ *
+ * Byte Transfer
+ * Enable Length Transfer Byte Address
+ * adr<6:5> adr<4:3> Length Enable Adder
+ * ---------------------------------------------
+ * 00 00 Byte 1110 0x000
+ * 01 00 Byte 1101 0x020
+ * 10 00 Byte 1011 0x040
+ * 11 00 Byte 0111 0x060
+ *
+ * 00 01 Word 1100 0x008
+ * 01 01 Word 1001 0x028 <= Not supported in this code.
+ * 10 01 Word 0011 0x048
+ *
+ * 00 10 Tribyte 1000 0x010
+ * 01 10 Tribyte 0001 0x030
+ *
+ * 10 11 Longword 0000 0x058
+ *
+ * Note that byte enables are asserted low.
+ *
+ */
+
+#define BYTE_ENABLE_SHIFT 5
+#define TRANSFER_LENGTH_SHIFT 3
+#define MEM_SP1_MASK 0x1fffffff /* Mem sparse space 1 mask is 29 bits */
+
+
+#define ALCOR_DMA_WIN_BASE (1024UL*1024UL*1024UL)
+#define ALCOR_DMA_WIN_SIZE (1024*1024*1024)
+
+/*
+ * 21171-CA Control and Status Registers (p4-1)
+ */
+#define ALCOR_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL)
+#define ALCOR_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
+#define ALCOR_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL)
+#define ALCOR_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
+#define ALCOR_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL)
+#define ALCOR_IOC_CFG (IDENT_ADDR + 0x8740000480UL)
+#define ALCOR_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL)
+
+/*
+ * 21171-CA Diagnostic Registers (p4-2)
+ */
+#define ALCOR_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL)
+#define ALCOR_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
+
+/*
+ * 21171-CA Performance Monitor registers (p4-3)
+ */
+#define ALCOR_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
+#define ALCOR_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
+
+/*
+ * 21171-CA Error registers (p4-3)
+ */
+#define ALCOR_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL)
+#define ALCOR_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL)
+#define ALCOR_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL)
+#define ALCOR_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL)
+#define ALCOR_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
+#define ALCOR_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL)
+#define ALCOR_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL)
+#define ALCOR_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL)
+#define ALCOR_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
+#define ALCOR_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
+#define ALCOR_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL)
+
+/*
+ * 2117A-CA PCI Address Translation Registers. I've only defined
+ * the first window fully as that's the only one that we're currently using.
+ * The other window bases are needed to disable the windows.
+ */
+#define ALCOR_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL)
+#define ALCOR_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL)
+#define ALCOR_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL)
+#define ALCOR_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL)
+
+#define ALCOR_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL)
+#define ALCOR_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL)
+#define ALCOR_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL)
+
+/*
+ * 21171-CA System configuration registers (p4-3)
+ */
+#define ALCOR_IOC_MCR (IDENT_ADDR + 0x8750000000UL)
+#define ALCOR_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL)
+#define ALCOR_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL)
+#define ALCOR_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL)
+#define ALCOR_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL)
+#define ALCOR_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL)
+#define ALCOR_IOC_MBAA (IDENT_ADDR + 0x8750000880UL)
+#define ALCOR_IOC_MBAC (IDENT_ADDR + 0x8750000900UL)
+#define ALCOR_IOC_MBAE (IDENT_ADDR + 0x8750000980UL)
+#define ALCOR_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL)
+#define ALCOR_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL)
+#define ALCOR_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL)
+
+/*
+ * Memory spaces:
+ */
+#define ALCOR_IACK_SC (IDENT_ADDR + 0x8720000000UL)
+#define ALCOR_CONF (IDENT_ADDR + 0x8700000000UL)
+#define ALCOR_IO (IDENT_ADDR + 0x8580000000UL)
+#define ALCOR_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
+#define ALCOR_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define ALCOR_IOC_STAT0_CMD 0xf
+#define ALCOR_IOC_STAT0_ERR (1<<4)
+#define ALCOR_IOC_STAT0_LOST (1<<5)
+#define ALCOR_IOC_STAT0_THIT (1<<6)
+#define ALCOR_IOC_STAT0_TREF (1<<7)
+#define ALCOR_IOC_STAT0_CODE_SHIFT 8
+#define ALCOR_IOC_STAT0_CODE_MASK 0x7
+#define ALCOR_IOC_STAT0_P_NBR_SHIFT 13
+#define ALCOR_IOC_STAT0_P_NBR_MASK 0x7ffff
+
+#define HAE_ADDRESS ALCOR_IOC_HAE_MEM
+
+#ifdef __KERNEL__
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+extern inline unsigned long virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + ALCOR_DMA_WIN_BASE;
+}
+
+extern inline void * bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - ALCOR_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * Alcor (the 2117x PCI/memory support chipset for the EV5 (21164)
+ * series of processors uses a sparse address mapping scheme to
+ * get at PCI memory and I/O.
+ */
+
+#define vuip volatile unsigned int *
+
+extern inline unsigned int __inb(unsigned long addr)
+{
+ long result = *(vuip) ((addr << 5) + ALCOR_IO + 0x00);
+ result >>= (addr & 3) * 8;
+ return 0xffUL & result;
+}
+
+extern inline void __outb(unsigned char b, unsigned long addr)
+{
+ unsigned int w;
+
+ asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+ *(vuip) ((addr << 5) + ALCOR_IO + 0x00) = w;
+ mb();
+}
+
+extern inline unsigned int __inw(unsigned long addr)
+{
+ long result = *(vuip) ((addr << 5) + ALCOR_IO + 0x08);
+ result >>= (addr & 3) * 8;
+ return 0xffffUL & result;
+}
+
+extern inline void __outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w;
+
+ asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+ *(vuip) ((addr << 5) + ALCOR_IO + 0x08) = w;
+ mb();
+}
+
+extern inline unsigned int __inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + ALCOR_IO + 0x18);
+}
+
+extern inline void __outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + ALCOR_IO + 0x18) = b;
+ mb();
+}
+
+
+/*
+ * Memory functions. 64-bit and 32-bit accesses are done through
+ * dense memory space, everything else through sparse space.
+ *
+ * For reading and writing 8 and 16 bit quantities we need to
+ * go through one of the three sparse address mapping regions
+ * and use the HAE_MEM CSR to provide some bits of the address.
+ * The following few routines use only sparse address region 1
+ * which gives 1Gbyte of accessible space which relates exactly
+ * to the amount of PCI memory mapping *into* system address space.
+ * See p 6-17 of the specification but it looks something like this:
+ *
+ * 21164 Address:
+ *
+ * 3 2 1
+ * 9876543210987654321098765432109876543210
+ * 1ZZZZ0.PCI.QW.Address............BBLL
+ *
+ * ZZ = SBZ
+ * BB = Byte offset
+ * LL = Transfer length
+ *
+ * PCI Address:
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * HHH....PCI.QW.Address........ 00
+ *
+ * HHH = 31:29 HAE_MEM CSR
+ *
+ */
+
+extern inline unsigned long __readb(unsigned long addr)
+{
+ unsigned long result, shift, msb;
+
+ shift = (addr & 0x3) * 8 ;
+ msb = addr & 0xE0000000 ;
+ addr &= MEM_SP1_MASK ;
+ if (msb != hae.cache) {
+ set_hae(msb);
+ }
+ result = *(vuip) ((addr << 5) + ALCOR_SPARSE_MEM + 0x00) ;
+ result >>= shift;
+ return 0xffUL & result;
+}
+
+extern inline unsigned long __readw(unsigned long addr)
+{
+ unsigned long result, shift, msb;
+
+ shift = (addr & 0x3) * 8;
+ msb = addr & 0xE0000000 ;
+ addr &= MEM_SP1_MASK ;
+ if (msb != hae.cache) {
+ set_hae(msb);
+ }
+ result = *(vuip) ((addr << 5) + ALCOR_SPARSE_MEM + 0x08);
+ result >>= shift;
+ return 0xffffUL & result;
+}
+
+extern inline unsigned long __readl(unsigned long addr)
+{
+ return *(vuip) (addr + ALCOR_DENSE_MEM);
+}
+
+extern inline void __writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= MEM_SP1_MASK ;
+ if (msb != hae.cache) {
+ set_hae(msb);
+ }
+ *(vuip) ((addr << 5) + ALCOR_SPARSE_MEM + 0x00) = b * 0x01010101;
+}
+
+extern inline void __writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= MEM_SP1_MASK ;
+ if (msb != hae.cache) {
+ set_hae(msb);
+ }
+ *(vuip) ((addr << 5) + ALCOR_SPARSE_MEM + 0x08) = b * 0x00010001;
+}
+
+extern inline void __writel(unsigned int b, unsigned long addr)
+{
+ *(vuip) (addr + ALCOR_DENSE_MEM) = b;
+}
+
+#define inb(port) \
+(__builtin_constant_p((port))?__inb(port):_inb(port))
+
+#define outb(x, port) \
+(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+
+#define readl(a) __readl((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+
+#undef vuip
+
+extern unsigned long alcor_init (unsigned long mem_start,
+ unsigned long mem_end);
+
+#endif /* __KERNEL__ */
+
+/*
+ * Data structure for handling ALCOR machine checks:
+ */
+struct el_ALCOR_sysdata_mcheck {
+ u_long coma_gcr;
+ u_long coma_edsr;
+ u_long coma_ter;
+ u_long coma_elar;
+ u_long coma_ehar;
+ u_long coma_ldlr;
+ u_long coma_ldhr;
+ u_long coma_base0;
+ u_long coma_base1;
+ u_long coma_base2;
+ u_long coma_cnfg0;
+ u_long coma_cnfg1;
+ u_long coma_cnfg2;
+ u_long epic_dcsr;
+ u_long epic_pear;
+ u_long epic_sear;
+ u_long epic_tbr1;
+ u_long epic_tbr2;
+ u_long epic_pbr1;
+ u_long epic_pbr2;
+ u_long epic_pmr1;
+ u_long epic_pmr2;
+ u_long epic_harx1;
+ u_long epic_harx2;
+ u_long epic_pmlt;
+ u_long epic_tag0;
+ u_long epic_tag1;
+ u_long epic_tag2;
+ u_long epic_tag3;
+ u_long epic_tag4;
+ u_long epic_tag5;
+ u_long epic_tag6;
+ u_long epic_tag7;
+ u_long epic_data0;
+ u_long epic_data1;
+ u_long epic_data2;
+ u_long epic_data3;
+ u_long epic_data4;
+ u_long epic_data5;
+ u_long epic_data6;
+ u_long epic_data7;
+};
+
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ADDR(x) (0x80 | (x))
+#define RTC_ALWAYS_BCD 0
+
+#endif /* __ALPHA_ALCOR__H__ */
#define fd_cacheflush(addr,size) /* nothing */
#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
SA_INTERRUPT|SA_SAMPLE_RANDOM, \
- "floppy")
-#define fd_free_irq() free_irq(FLOPPY_IRQ);
+ "floppy", NULL)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
__inline__ void virtual_dma_init(void)
{
# include <asm/lca.h> /* get chip-specific definitions */
#elif defined(CONFIG_ALPHA_APECS)
# include <asm/apecs.h> /* get chip-specific definitions */
+#elif defined(CONFIG_ALPHA_ALCOR)
+# include <asm/alcor.h> /* get chip-specific definitions */
#else
# include <asm/jensen.h>
#endif
#include <linux/linkage.h>
#include <linux/config.h>
-#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || defined(CONFIG_ALPHA_EB164)
# define NR_IRQS 33
#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
# define NR_IRQS 32
* work correctly and can thus not be used (explaining the lack of PAL-code
* support).
*/
-#ifdef CONFIG_EV5
+#ifdef CONFIG_ALPHA_EV5
#define MAX_ASN 127
#else
#define MAX_ASN 63
*/
extern inline void get_mmu_context(struct task_struct *p)
{
-#ifdef CONFIG_EV5
+#ifdef CONFIG_ALPHA_EV5
static unsigned long asn_cache = ASN_FIRST_VERSION;
struct mm_struct * mm = p->mm;
- unsigned long asn = mm->context;
- /* Check if our ASN is of an older version and thus invalid */
- if ((asn_cache ^ asn) & ASN_VERSION_MASK) {
- /* get a new asn of the current version */
- asn = asn_cache++;
- /* check if it's legal.. */
- if ((asn & ~ASN_VERSION_MASK) > MAX_ASN) {
- /* start a new version, invalidate all old asn's */
- tbiap(); imb();
- asn_cache = (asn_cache & ASN_VERSION_MASK) + ASN_FIRST_VERSION;
- if (!asn_cache)
- asn_cache = ASN_FIRST_VERSION;
+ if (mm) {
+ unsigned long asn = mm->context;
+ /* Check if our ASN is of an older version and thus invalid */
+ if ((asn_cache ^ asn) & ASN_VERSION_MASK) {
+ /* get a new asn of the current version */
asn = asn_cache++;
+ /* check if it's legal.. */
+ if ((asn & ~ASN_VERSION_MASK) > MAX_ASN) {
+ /* start a new version, invalidate all old asn's */
+ tbiap(); imb();
+ asn_cache = (asn_cache & ASN_VERSION_MASK) + ASN_FIRST_VERSION;
+ if (!asn_cache)
+ asn_cache = ASN_FIRST_VERSION;
+ asn = asn_cache++;
+ }
+ mm->context = asn; /* full version + asn */
+ p->tss.asn = asn & ~ASN_VERSION_MASK; /* just asn */
}
- mm->context = asn; /* full version + asn */
- p->tss.asn = asn & ~ASN_VERSION_MASK; /* just asn */
}
#endif
}
* the changes in signal handling. LBT 010493.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
*/
#define SA_NOCLDSTOP 0x00000004
#define SA_INTERRUPT 0x20000000
#define SA_NOMASK 0x00000008
#define SA_ONESHOT 0x00000010
+#define SA_SHIRQ 0x00000020
#ifdef __KERNEL__
/*
#define halt() __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_halt) : "memory")
-extern void alpha_switch_to(unsigned long pctxp);
-
#define switch_to(p) do { \
current_set[0] = p; \
alpha_switch_to((unsigned long) &(p)->tss - 0xfffffc0000000000); \
} while (0)
+extern void alpha_switch_to(unsigned long pctxp);
+
extern void imb(void);
#define mb() \
#define fd_cacheflush(addr,size) /* nothing */
#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
SA_INTERRUPT|SA_SAMPLE_RANDOM, \
- "floppy")
-#define fd_free_irq() free_irq(FLOPPY_IRQ);
+ "floppy", NULL)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
__inline__ void virtual_dma_init(void)
{
* the changes in signal handling. LBT 010493.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
*/
#define SA_NOCLDSTOP 1
+#define SA_SHIRQ 0x04000000
#define SA_STACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_INTERRUPT 0x20000000
* Private routines/data
*/
+extern int smp_found_config;
extern void smp_scan_config(unsigned long, unsigned long);
extern unsigned long smp_alloc_memory(unsigned long mem_base);
extern unsigned char *apic_reg;
extern unsigned char *kernel_stacks[NR_CPUS];
extern unsigned char boot_cpu_id;
extern unsigned long cpu_present_map;
+extern volatile int cpu_number_map[NR_CPUS];
extern volatile unsigned long smp_invalidate_needed;
extern void smp_invalidate(void);
extern volatile unsigned long kernel_flag, kernel_counter;
extern volatile unsigned char active_kernel_processor;
-extern void smp_message_irq(int cpl, struct pt_regs *regs);
-extern void smp_reschedule_irq(int cpl, struct pt_regs *regs);
+extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
+extern void smp_reschedule_irq(int cpl, void *dev_id, struct pt_regs *regs);
extern unsigned long ipi_count;
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern volatile unsigned long kernel_counter;
#define fd_cacheflush(addr, size) feature->fd_cacheflush((void *)addr, size)
#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
SA_INTERRUPT|SA_SAMPLE_RANDOM, \
- "floppy")
-#define fd_free_irq() free_irq(FLOPPY_IRQ);
+ "floppy", NULL)
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
#define MAX_BUFFER_SECTORS 24
#define virtual_dma_init() \
* the changes in signal handling. LBT 010493.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
*/
#define SA_STACK 0x1
#define SA_ONSTACK SA_STACK
#define SA_INTERRUPT 0x01000000
#define SA_NOMASK 0x02000000
#define SA_ONESHOT 0x04000000
+#define SA_SHIRQ 0x08000000
#ifdef __KERNEL__
/*
* the changes in signal handling. LBT 010493.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
*/
#define SA_NOCLDSTOP 1
+#define SA_SHIRQ 0x04000000
#define SA_STACK 0x08000000
#define SA_RESTART 0x10000000
#define SA_INTERRUPT 0x20000000
}
/* Our low-level entry point in arch/sparc/kernel/entry.S */
-extern void floppy_hardint(int irq, struct pt_regs *regs);
+extern void floppy_hardint(int irq, void *dev_id, struct pt_regs *regs);
static int sun_fd_request_irq(void)
{
if(!once) {
once = 1;
- error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy");
+ error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy", NULL);
return ((error == 0) ? 0 : -1);
} else return 0;
}
* the changes in signal handling. LBT 010493.
* SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
* SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
*/
#define SA_NOCLDSTOP SV_IGNCHILD
#define SA_STACK SV_SSTACK
#define SA_INTERRUPT SV_INTR
#define SA_NOMASK 0x10
#define SA_ONESHOT 0x20
+#define SA_SHIRQ 0x40
#define SIG_BLOCK 0x00 /* for blocking signals */
#define SIG_UNBLOCK 0x40 /* for unblocking signals */
struct ddpshdr
{
/* FIXME for bigendians */
- __u8 dsh_sport;
- __u8 dsh_dport;
__u16 dsh_len:10, dsh_pad:6;
+ __u8 dsh_dport;
+ __u8 dsh_sport;
/* And netatalk apps expect to stick the type in themselves */
};
extern struct gendisk *gendisk_head; /* linked list of disks */
+/*
+ * disk_name() is used by genhd.c and md.c.
+ * It formats the devicename of the indicated disk
+ * into the supplied buffer, and returns a pointer
+ * to that same buffer (for convenience).
+ */
+char *disk_name (struct gendisk *hd, int minor, char *buf);
+
#endif
#define ARPHRD_FRAD 770 /* Frame Relay */
#define ARPHRD_SKIP 771 /* SKIP vif */
#define ARPHRD_LOOPBACK 772 /* Loopback device */
+#define ARPHRD_LOCALTLK 773 /* Localtalk device */
/* ARP protocol opcodes. */
#define ARPOP_REQUEST 1 /* ARP request */
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
#define ETH_P_IPX 0x8137 /* IPX over DIX */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
+
+/*
+ * Non DIX types. Won't clash for 1500 types.
+ */
+
#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */
#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */
#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */
#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
+#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudeo type */
/* This is an Ethernet frame header. */
struct ethhdr {
#include <linux/kernel.h>
#include <asm/bitops.h>
+struct irqaction {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ unsigned long mask;
+ const char *name;
+ void *dev_id;
+ struct irqaction *next;
+};
+
+
struct bh_struct {
void (*routine)(void *);
void *data;
extern int send_sig(unsigned long sig,struct task_struct * p,int priv);
extern int in_group_p(gid_t grp);
-extern int request_irq(unsigned int irq,void (*handler)(int, struct pt_regs *),
- unsigned long flags, const char *device);
-extern void free_irq(unsigned int irq);
+extern int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags,
+ const char *device,
+ void *dev_id);
+extern void free_irq(unsigned int irq, void *dev_id);
extern void copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
extern void flush_thread(void);
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);
-static void xd_interrupt_handler (int irq, struct pt_regs * regs);
+static void xd_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs);
static u_char xd_setup_dma (u_char opcode,u_char *buffer,u_int count);
static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control);
static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout);
* Create the slave init tasks as sharing pid 0.
*/
- for(i=1;i<smp_num_cpus;i++)
+ for (i=0; i<NR_CPUS; i++)
{
/*
- * We use kernel_thread for the idlers which are
- * unlocked tasks running in kernel space.
+ * This should only do anything if the mapping
+ * corresponds to a live CPU which is not the boot CPU.
*/
- kernel_thread(cpu_idle, NULL, CLONE_PID);
- /*
- * Assume linear processor numbering
- */
- current_set[i]=task[i];
- current_set[i]->processor=i;
+ if (cpu_number_map[i] > 0)
+ {
+ /*
+ * We use kernel_thread for the idlers which are
+ * unlocked tasks running in kernel space.
+ */
+ kernel_thread(cpu_idle, NULL, CLONE_PID);
+ /*
+ * Don't assume linear processor numbering
+ */
+ current_set[i]=task[cpu_number_map[i]];
+ current_set[i]->processor=i;
+ }
}
}
return old_fsgid;
}
-asmlinkage int sys_times(struct tms * tbuf)
+asmlinkage long sys_times(struct tms * tbuf)
{
if (tbuf) {
int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
struct aarp_entry *a;
unsigned long flags;
+ /*
+ * Check for localtalk first
+ */
+
+ if(dev->type==ARPHRD_LOCALTLK)
+ {
+ struct at_addr *at=atalk_find_dev_addr(dev);
+ int ft=2;
+
+ /*
+ * Compressable ?
+ */
+
+ if(at->s_net==sa->s_net)
+ {
+ skb_pull(skb,sizeof(struct ddpehdr)-4);
+ /*
+ * The uper two remaining bytes are the port
+ * numbers we just happen to need. Now put the
+ * length in the lower two.
+ */
+ *((__u16 *)skb->data)=htons(skb->len);
+ ft=1;
+ }
+ /*
+ * Nice and easy. No AARP type protocols occur here
+ * so we can just shovel it out with a 3 byte LLAP header
+ */
+
+ skb_push(skb,3);
+ skb->data[0]=sa->s_node;
+ skb->data[1]=at->s_node;
+ skb->data[2]=ft;
+
+ if(skb->sk==NULL)
+ dev_queue_xmit(skb, skb->dev, SOPRI_NORMAL);
+ else
+ dev_queue_xmit(skb, skb->dev, skb->sk->priority);
+ return 1;
+ }
+
/*
* Non ELAP we cannot do.
*/
* socket.
* Alan Cox : Added firewall hooks.
* Alan Cox : Supports new ARPHRD_LOOPBACK
+ * Christer Weinigel : Routing and /proc fixes.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#ifdef CONFIG_ATALK
-#define APPLETALK_DEBUG
+#undef APPLETALK_DEBUG
#ifdef APPLETALK_DEBUG
{
len += sprintf (buffer+len,"%02X ", s->type);
len += sprintf (buffer+len,"%04X:%02X:%02X ",
- s->protinfo.af_at.src_net,s->protinfo.af_at.src_node,s->protinfo.af_at.src_port);
+ ntohs(s->protinfo.af_at.src_net),
+ s->protinfo.af_at.src_node,
+ s->protinfo.af_at.src_port);
len += sprintf (buffer+len,"%04X:%02X:%02X ",
- s->protinfo.af_at.dest_net,s->protinfo.af_at.dest_node,s->protinfo.af_at.dest_port);
+ ntohs(s->protinfo.af_at.dest_net),
+ s->protinfo.af_at.dest_node,
+ s->protinfo.af_at.dest_port);
len += sprintf (buffer+len,"%08lX:%08lX ", s->wmem_alloc, s->rmem_alloc);
len += sprintf (buffer+len,"%02X %d\n", s->state, SOCK_INODE(s->socket)->i_uid);
return -EPERM;
if(sa->sat_family!=AF_APPLETALK)
return -EINVAL;
- if(dev->type!=ARPHRD_ETHER&&dev->type!=ARPHRD_LOOPBACK)
+ if(dev->type!=ARPHRD_ETHER&&dev->type!=ARPHRD_LOOPBACK
+ &&dev->type!=ARPHRD_LOCALTLK)
return -EPROTONOSUPPORT;
nr=(struct netrange *)&sa->sat_zero[0];
- if(nr->nr_phase!=2)
+ /*
+ * Phase 1 is fine on localtalk but we don't
+ * do Ethertalk phase 1. Anyone wanting to add
+ * it go ahead.
+ */
+ if(dev->type==ARPHRD_ETHER && nr->nr_phase!=2)
return -EPROTONOSUPPORT;
if(sa->sat_addr.s_node==ATADDR_BCAST || sa->sat_addr.s_node == 254)
return -EINVAL;
if(atrtr_default.dev)
{
rt=&atrtr_default;
- len += sprintf (buffer+len,"Default %5d:%-3d %-4d %s\n",
+ len += sprintf (buffer+len,"Default %04X:%02X %-4d %s\n",
ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags,
rt->dev->name);
}
for (rt = atalk_router_list; rt != NULL; rt = rt->next)
{
- len += sprintf (buffer+len,"%04X:%02X %5d:%-3d %-4d %s\n",
+ len += sprintf (buffer+len,"%04X:%02X %04X:%02X %-4d %s\n",
ntohs(rt->target.s_net),rt->target.s_node,
ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags,
rt->dev->name);
* extracted.
*/
-int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
{
atalk_socket *sock;
struct ddpehdr *ddp=(void *)skb->h.raw;
}
ddp->deh_hops++;
+ /*
+ * Route goes through another gateway, so
+ * set the target to the gateway instead.
+ */
+
+ if(rt->flags&RTF_GATEWAY)
+ {
+ ta.s_net = rt->gateway.s_net;
+ ta.s_node = rt->gateway.s_node;
+ }
+
/* Fix up skb->len field */
skb_trim(skb,min(origlen, rt->dev->hard_header_len +
ddp_dl->header_length + ddp->deh_len));
/*
* Send the buffer onwards
*/
+
+ skb->arp = 1; /* Resolved */
+
if(aarp_send_ddp(rt->dev, skb, &ta, NULL)==-1)
kfree_skb(skb, FREE_READ);
return 0;
return(0);
}
+/*
+ * Receive a localtalk frame. We make some demands on the caller here.
+ * Caller must provide enough headroom on the packet to pull the short
+ * header and append a long one.
+ */
+
+
+static int ltalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+ struct ddpehdr *ddp;
+ struct at_addr *ap;
+ /*
+ * Expand any short form frames.
+ */
+
+ if(skb->mac.raw[2]==1)
+ {
+ /*
+ * Find our address.
+ */
+
+ ap=atalk_find_dev_addr(dev);
+ if(ap==NULL || skb->len<sizeof(struct ddpshdr))
+ {
+ kfree_skb(skb, FREE_READ);
+ return 0;
+ }
+
+ /*
+ * The push leaves us with a ddephdr not an shdr, and
+ * handily the port bytes in the right place preset.
+ */
+
+ skb_push(skb, sizeof(*ddp)-4);
+ ddp=(struct ddpehdr *)skb->data;
+
+ /*
+ * Now fill in the long header.
+ */
+
+ /*
+ * These two first. The mac overlays the new source/dest
+ * network information so we MUST copy these before
+ * we write the network numbers !
+ */
+
+ ddp->deh_dnode=skb->mac.raw[0]; /* From physical header */
+ ddp->deh_snode=skb->mac.raw[1]; /* From physical header */
+
+ ddp->deh_dnet=ap->s_net; /* Network number */
+ ddp->deh_snet=ap->s_net;
+ ddp->deh_sum=0; /* No checksum */
+ /*
+ * Not sure about this bit...
+ */
+ ddp->deh_len=skb->len;
+ ddp->deh_hops=15; /* Non routable, so force a drop
+ if we slip up later */
+ *((__u16 *)ddp)=htons(*((__u16 *)ddp)); /* Mend the byte order */
+ }
+ return atalk_rcv(skb,dev,pt);
+}
+
static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
{
atalk_socket *sk=(atalk_socket *)sock->data;
0
};
+struct packet_type ltalk_packet_type=
+{
+ 0,
+ NULL,
+ ltalk_rcv,
+ NULL,
+ NULL
+};
+
/* Called by proto.c on kernel start up */
void atalk_proto_init(struct net_proto *pro)
(void) sock_register(atalk_proto_ops.family, &atalk_proto_ops);
if ((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL)
printk("Unable to register DDP with SNAP.\n");
+
+ ltalk_packet_type.type=htons(ETH_P_LOCALTALK);
+ dev_add_pack(<alk_packet_type);
+
register_netdevice_notifier(&ddp_notifier);
aarp_proto_init();
atalk_if_get_info
});
- printk("Appletalk 0.14 for Linux NET3.032\n");
+ printk("Appletalk 0.16 for Linux NET3.033\n");
}
#endif
* Alan Cox : MAC layer pointers/new format.
* Paul Gortmaker : eth_copy_and_sum shouldn't csum padding.
* Alan Cox : Protect against forwarding explosions with
- * older network drivers and IFF_ALLMULTI
+ * older network drivers and IFF_ALLMULTI.
+ * Christer Weinigel : Better rebuild header message.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
if(eth->h_proto != htons(ETH_P_IP))
{
- printk("eth_rebuild_header: Don't know how to resolve type %d addresses?\n",(int)eth->h_proto);
+ printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",dev->name,(int)eth->h_proto);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return 0;
}
/*
* Allow only if both are setting reuse.
*/
- if(sk2->reuse && sk->reuse)
+ if(sk2->reuse && sk->reuse && sk2->state!=TCP_LISTEN)
continue;
sti();
return(-EADDRINUSE);
* are needed for AMPRnet AX.25 paths.
*/
else if (old_mtu > 216)
- old_mtu = 216;
+ new_mtu = 216;
else if (old_mtu > 128)
- old_mtu = 128;
+ new_mtu = 128;
else
/*
* Despair..
if (offset<128)
{
- sprintf(buffer,"%-127s\n","Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tHH\tARP\n");
+ sprintf(buffer,"%-127s\n","Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tHH\tARP");
len = 128;
}
#ifdef CONFIG_IPX_INTERN
len += sprintf(buffer+len,
"%08lX:%02X%02X%02X%02X%02X%02X:%04X ",
- htonl(s->ipx_intrfc->if_netnum),
+ htonl(s->protinfo.af_ipx.intrfc->if_netnum),
s->protinfo.af_ipx.node[0],
s->protinfo.af_ipx.node[1],
s->protinfo.af_ipx.node[2],
*/
int
dialog_checklist (const char *title, const char *prompt, int height, int width,
- int list_height, int item_no, const char * const * items, int flag,
- int separate_output)
+ int list_height, int item_no, const char * const * items, int flag)
{
int i, x, y, cur_x, cur_y, box_x, box_y;
int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
{
if(cfg->tok == tok_dep_tristate)
{
- printf("\tif {$%s == 2 } then {\n"
+ printf("\tif {$%s == 0 } then {\n"
"\t\twrite_variable $cfg $autocfg %s $notset $notmod\n"
"\t} else {\n"
- "\t\twrite_variable $cfg $autocfg %s $%s %s\n"
+ "\t\twrite_variable $cfg $autocfg %s $%s $%s\n"
"\t}\n",
cfg->depend.str,
cfg->optionname,