E: rth@cygnus.com
E: richard@gnu.org
D: Alpha/ELF, gcc, binutils, and glibc
-S: 5450 Mayme #25
-S: San Jose, California 95129
+S: 50 E. Middlefield #10
+S: Mountain View, California 94043-3822
S: USA
N: Sebastian Hetze
discipline, these cases get detected quickly and safely.
Theodore Ts'o
- 31-Mar-94
+ 31 Mar 94
The magic table is current to Linux 2.1.55.
<mailto:mec@shout.net>
22 Sep 1997
+Now it should be up to date with Linux 2.1.112. Because
+we are in feature freeze time it is very unlikely that
+something will change before 2.2.x. The entries are
+sorted by number field.
+ Krzysztof G. Baranowski
+ <mailto: kgb@knm.org.pl>
+ 29 Jul 1998
-Magic Name Number Structure File
+Magic Name Number Structure File
===========================================================================
-
+PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h
RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h
APM_BIOS_MAGIC 0x4101 apm_bios_struct include/linux/apm_bios.h
CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h
FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h
+PTY_MAGIC 0x5001 (none at the moment)
+ drivers/char/pty.c
PPP_MAGIC 0x5002 ppp include/linux/if_ppp.h
SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h
SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h
SLIP_MAGIC 0x5302 slip drivers/net/slip.h
STRIP_MAGIC 0x5303 strip drivers/net/strip.c
X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h
+SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h
AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h
ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h
TTY_MAGIC 0x5401 tty_struct include/linux/tty.h
TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h
TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h
SCC_MAGIC 0x8530 scc_channel include/linux/scc.h
+SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h
+CG_MAGIC 0x090255 ufs_cylinder_group include/linux/ufs_fs.h
RPORT_MAGIC 0x525001 r_port drivers/char/rocket_int.h
-SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c
+GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h
+NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h
SLAB_RED_MAGIC2 0x170fc2a5 (any) mm/slab.c
+BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c
+ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data
+ drivers/isdn/isdn_x25iface.h
ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h
+LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c
+LSOMAGIC 0x2a3c4e3c lso drivers/fc4/fc.c
+WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h
+CODA_CNODE_MAGIC 0x47114711 coda_inode_info include/linux/coda_fs_i.h
ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h
ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s include/linux/isdn.h
STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h
+SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c
ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h
SLAB_RED_MAGIC1 0x5a2cf071 (any) mm/slab.c
STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h
-EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h
+EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h
PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h
+LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h
STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h
+NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h
STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h
SLAB_MAGIC_ALLOC 0xa5c32f2b kmem_slab_s mm/slab.c
SLAB_MAGIC_DESTROYED 0xb2f23c5a kmem_slab_s mm/slab.c
--- /dev/null
+NOTES ON RADIOTRACK CARD CONTROL
+by Stephen M. Benoit (benoits@servicepro.com) Dec 14, 1996
+----------------------------------------------------------------------------
+
+Document version 1.0
+
+ACKNOWLEDGMENTS
+----------------
+This document was made based on 'C' code for Linux from Gideon le Grange
+(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from
+Frans Brinkman (brinkman@esd.nl) in 1996. The results reported here are from
+experiments that the author performed on his own setup, so your mileage may
+vary... I make no guarantees, claims or warrantees to the suitability or
+validity of this information. No other documentation on the AIMS
+Lab (http://www.aimslab.com/) RadioTrack card was made available to the
+author. This document is offered in the hopes that it might help users who
+want to use the RadioTrack card in an environment other than MS Windows.
+
+WHY THIS DOCUMENT?
+------------------
+I have a RadioTrack card from back when I ran an MS-Windows platform. After
+converting to Linux, I found Gideon le Grange's command-line software for
+running the card, and found that it was good! Frans Brinkman made a
+comfortable X-windows interface, and added a scanning feature. For hack
+value, I wanted to see if the tuner could be tuned beyond the usual FM radio
+broadcast band, so I could pick up the audio carriers from North American
+broadcast TV channels, situated just below and above the 87.0-109.0 MHz range.
+I did not get much success, but I learned about programming ioports under
+Linux and gained some insights about the hardware design used for the card.
+
+So, without further delay, here are the details.
+
+
+PHYSICAL DESCRIPTION
+--------------------
+The RadioTrack card is an ISA 8-bit FM radio card. The radio frequency (RF)
+input is simply an antenna lead, and the output is a power audio signal
+available through a miniature phono plug. Its RF frequencies of operation are
+more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast
+band). Although the registers can be programmed to request frequencies beyond
+these limits, experiments did not give promising results. The variable
+frequency oscillator (VFO) that demodulates the intermediate frequency (IF)
+signal probably has a small range of useful frequencies, and wraps around or
+gets clipped beyond the limits mentioned above.
+
+
+CONTROLLING THE CARD WITH IOPORT
+--------------------------------
+The RadioTrack (base) ioport is configurable for 0x30c or 0x20c. Only one
+ioport seems to be involved. The ioport decoding circuitry must be pretty
+simple, as individual ioport bits are directly matched to specific functions
+(or blocks) of the radio card. This way, many functions can be changed in
+parallel with one write to the ioport. The only feedback available through
+the ioports appears to be the "Stereo Detect" bit.
+
+The bits of the ioport are arranged as follows:
+
+ MSb LSb
++------+------+------+--------+--------+-------+---------+--------+
+| VolA | VolB | ???? | Stereo | Radio | TuneA | TuneB | Tune |
+| (+) | (-) | | Detect | Audio | (bit) | (latch) | Update |
+| | | | Enable | Enable | | | Enable |
++------+------+------+--------+--------+-------+---------+--------+
+
+
+VolA . VolB [AB......]
+-----------
+0 0 : audio mute
+0 1 : volume + (some delay required)
+1 0 : volume - (some delay required)
+1 1 : stay at present volume
+
+Stereo Detect Enable [...S....]
+--------------------
+0 : No Detect
+1 : Detect
+
+ Results available by reading ioport >60 msec after last port write.
+ 0xff ==> no stereo detected, 0xfd ==> stereo detected.
+
+Radio to Audio (path) Enable [....R...]
+----------------------------
+0 : Disable path (silence)
+1 : Enable path (audio produced)
+
+TuneA . TuneB [.....AB.]
+-------------
+0 0 : "zero" bit phase 1
+0 1 : "zero" bit phase 2
+
+1 0 : "one" bit phase 1
+1 1 : "one" bit phase 2
+
+ 24-bit code, where bits = (freq*40) + 10486188.
+ The Most Significant 11 bits must be 1010 xxxx 0x0 to be valid.
+ The bits are shifted in LSb first.
+
+Tune Update Enable [.......T]
+------------------
+0 : Tuner held constant
+1 : Tuner updating in progress
+
+
+PROGRAMMING EXAMPLES
+--------------------
+Default: BASE <-- 0xc8 (current volume, no stereo detect,
+ radio enable, tuner adjust disable)
+
+Card Off: BASE <-- 0x00 (audio mute, no stereo detect,
+ radio disable, tuner adjust disable)
+
+Card On: BASE <-- 0x00 (see "Card Off", clears any unfinished business)
+ BASE <-- 0xc8 (see "Default")
+
+Volume Down: BASE <-- 0x48 (volume down, no stereo detect,
+ radio enable, tuner adjust disable)
+ * wait 10 msec *
+ BASE <-- 0xc8 (see "Default")
+
+Volume Up: BASE <-- 0x88 (volume up, no stereo detect,
+ radio enable, tuner adjust disable)
+ * wait 10 msec *
+ BASE <-- 0xc8 (see "Default")
+
+Check Stereo: BASE <-- 0xd8 (current volume, stereo detect,
+ radio enable, tuner adjust disable)
+ * wait 100 msec *
+ x <-- BASE (read ioport)
+ BASE <-- 0xc8 (see "Default")
+
+ x=0xff ==> "not stereo", x=0xfd ==> "stereo detected"
+
+Set Frequency: code = (freq*40) + 10486188
+ foreach of the 24 bits in code,
+ (from Least to Most Significant):
+ to write a "zero" bit,
+ BASE <-- 0x01 (audio mute, no stereo detect, radio
+ disable, "zero" bit phase 1, tuner adjust)
+ BASE <-- 0x03 (audio mute, no stereo detect, radio
+ disable, "zero" bit phase 2, tuner adjust)
+ to write a "one" bit,
+ BASE <-- 0x05 (audio mute, no stereo detect, radio
+ disable, "one" bit phase 1, tuner adjust)
+ BASE <-- 0x07 (audio mute, no stereo detect, radio
+ disable, "one" bit phase 2, tuner adjust)
+
+----------------------------------------------------------------------------
--- /dev/null
+1998-08-06 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.7.2
+
+ * After A/D calibration, do an explicit set to the line input,
+ rather than using set_recsrc
+
+1998-07-20 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.7.1
+
+ * Add more OSS ioctls
+
+1998-07-19 Andrew Veliath <andrewtv@usa.net>
+
+ * Update doc file
+
+ * Bring back DIGITAL1 with digital parameter to msnd_pinnacle.c
+ and CONFIG_MSNDPIN_DIGITAL. I'm not sure this actually works,
+ since I find audio playback goes into a very speeded mode of
+ operation, however it might be due to a lack of a digital
+ source, which I don't have to test.
+
+1998-07-18 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.7.0
+
+ * Can now compile with Alan Cox' 2.0.34-modular-sound patch (so
+ now it requires >= 2.1.106 or 2.0.34-ms) (note for 2.0.34-ms it
+ is in the Experimental section)
+
+ * More modularization, consolidation, also some MIDI hooks
+ installed for future MIDI modules
+
+ * Write flush
+
+ * Change default speed, channels, bit size to OSS/Free defaults
+
+1998-06-02 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.5b
+
+ * Fix version detection
+
+ * Remove underflow and overflow resets (delay was too long)
+
+ * Replace spinlocked bitops with atomic bit ops
+
+1998-05-27 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.5a
+
+ * Better recovery from underflow or overflow conditions
+
+ * Fix a deadlock condition with one thread reading and the other
+ writing
+
+1998-05-26 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.5
+
+ * Separate reset queue functions for play and record
+
+ * Add delays in dsp_halt
+
+1998-05-24 Andrew Veliath <andrewtv@usa.net>
+
+ * Add a check for Linux >= 2.1.95
+
+ * Remove DIGITAL1 input until I figure out how to make it work
+
+ * Add HAVE_DSPCODEH which when not defined will load firmware from
+ files using mod_firmware_load, then release memory after they
+ are uploaded (requires reorganized OSS).
+
+1998-05-22 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.4c
+
+ * Hopefully fix the mixer volume problem
+
+1998-05-19 Andrew Veliath <andrewtv@usa.net>
+
+ * Add __initfuncs and __initdatas to reduce resident code size
+
+ * Move bunch of code around, remove some protos
+
+ * Integrate preliminary changes for Alan Cox's OSS reorganization
+ for non-OSS drivers to coexist with OSS devices on the same
+ major. To compile standalone, must now define STANDALONE.
+
+1998-05-16 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.4b
+
+ * Integrated older card support into a unified driver, tested on a
+ MultiSound Classic c/o Kendrick Vargas.
+
+1998-05-15 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.4
+
+ * Fix read/write return values
+
+1998-05-13 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.3
+
+ * Stop play gracefully
+
+ * Add busy flag
+
+ * Add major and calibrate_signal module parameters
+
+ * Add ADC calibration
+
+ * Add some OSS compatibility ioctls
+
+ * Add mixer record selection
+
+ * Add O_NONBLOCK support, separate read/write wait queues
+
+ * Add sample bit size ioctl, expanded sample rate ioctl
+
+ * Playback suspension now resumes
+
+ * Use signal_pending after interruptible_sleep_on
+
+ * Add recording, change ints to bit flags
+
+1998-05-11 Andrew Veliath <andrewtv@usa.net>
+
+ * Update version to 0.2
+
+ * Add preliminary playback support
+
+ * Use new Turtle Beach DSP code
\ No newline at end of file
~~~~~~~~~~~~~~~~~~
Currently digital audio and mixer functionality is supported. (memory
-mapped digital audio is not yet supported). MultiSound support is
-fully modularized, and can only be used as modules:
+mapped digital audio is not yet supported). Modular MultiSound
+support is composed of the following modules:
msnd - MultiSound base (requires soundcore)
msnd_classic - Base audio/mixer support for Classic, Monetery and
msnd_classic, msnd_pinnacle Additional Options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-fifosize The digital audio FIFOs, in kilobytes. The default is
- 64kB (two FIFOs are allocated, so this uses up 128kB).
+fifosize The digital audio FIFOs, in kilobytes. The
+ default is 64kB (two FIFOs are allocated, so
+ this uses up 128kB).
calibrate_signal Setting this to one calibrates the ADCs to the
signal, zero calibrates to the card (defaults
to zero).
+msnd_pinnacle Additional Options
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+digital Specify digital=1 to enable the S/PDIF input
+ if you have the digital daughterboard
+ adapter. This will enable access to the
+ DIGITAL1 input for the soundcard in the mixer.
+ Some mixer programs might have trouble setting
+ the DIGITAL1 source as an input. If you have
+ trouble, you can try the setdigital.c program
+ at the bottom of this document.
+
+
Obtaining and Creating Firmware Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cp DSPCODE/MSNDPERM.REB /etc/sound/msndperm.bin
When configuring the Linux kernel, specify /etc/sound/msndinit.bin and
-/etc/sound/msndperm.bin for the two firmware files.
+/etc/sound/msndperm.bin for the two firmware files (Linux kernel
+versions older than 2.2 do not ask for firmware paths, and are
+hardcoded to /etc/sound).
For the Pinnacle/Fiji
-- conv.l start --
%%
-[ \n\t,\r] ;
-\;.* ;
-DB ;
+[ \n\t,\r]
+\;.*
+DB
[0-9A-Fa-f]+H { int n; sscanf(yytext, "%xH", &n); printf("%c", n); }
-- conv.l end --
The conv (and conv.l) program is not needed after conversion and can
be safely deleted. Then, when configuring the Linux kernel, specify
/etc/sound/pndspini.bin and /etc/sound/pndsperm.bin for the two
-firmware files.
+firmware files (Linux kernel versions older than 2.2 do not ask for
+firmware paths, and are hardcoded to /etc/sound).
+
+
+Recording from the S/PDIF Input
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you have a Pinnacle or Fiji with S/PDIF input and want to set it as
+the input source, you can use this program if you have trouble trying
+to do it with a mixer program (be sure to insert the module with the
+digital=1 option).
+
+Compile with:
+cc -O setdigital.c -o setdigital
+
+-- start setdigital.c --
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ unsigned long recmask, recsrc;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: setdigital <mixer device>\n");
+ exit(1);
+ } else
+
+ if ((fd = open(argv[1], O_RDWR)) < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) < 0) {
+ fprintf(stderr, "error: ioctl read recmask failed\n");
+ perror("ioctl");
+ close(fd);
+ exit(1);
+ }
+
+ if (!(recmask & SOUND_MASK_DIGITAL1)) {
+ fprintf(stderr, "error: cannot find DIGITAL1 device in mixer\n");
+ close(fd);
+ exit(1);
+ }
+
+ if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) < 0) {
+ fprintf(stderr, "error: ioctl read recsrc failed\n");
+ perror("ioctl");
+ close(fd);
+ exit(1);
+ }
+
+ recsrc |= SOUND_MASK_DIGITAL1;
+
+ if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) < 0) {
+ fprintf(stderr, "error: ioctl write recsrc failed\n");
+ perror("ioctl");
+ close(fd);
+ exit(1);
+ }
+
+ close(fd);
+
+ return 0;
+}
+-- end setdigital.c --
-OPL3-SA sound driver (opl3sa.o)
+OPL3-SA1 sound driver (opl3sa.o)
-The Yamaha OPL3-SAx sound chip is usually found built into motherboards, and
+---
+Note: This howto only describes how to setup the OPL3-SA1 chip; this info
+does not apply to the SA2, SA3, or SA4. Contact hannu@opensound.com for
+the support details of these other SAx chips.
+---
+
+The Yamaha OPL3-SA1 sound chip is usually found built into motherboards, and
it's a decent little chip offering a WSS mode, a SB Pro emulation mode, MPU401
and OPL3 FM Synth capabilities.
Questions? Comments?
<stiker@northlink.com>
-
- An OSS/Free Driver for WaveFront soundcards
- (Turtle Beach Maui, Tropez, Tropez Plus)
+ An OSS/Free Driver for WaveFront soundcards
+ (Turtle Beach Maui, Tropez, Tropez Plus)
- Paul Barton-Davis, July 1998
+ Paul Barton-Davis, July 1998
+
+ VERSION 0.2.4
Driver Status
-------------
-Requires: Kernel 2.1.106 or later
-
-As of 7/3/1998, this driver is currently in *BETA* state. This means
+Requires: Kernel 2.1.106 or later (a version of the driver is included
+with kernels 2.1.109 and above)
+
+As of 7/20/1998, this driver is currently in *BETA* state. This means
that it compiles and runs, and that I use it on my system (Linux
2.1.106) with some reasonably demanding applications and uses. I
believe the code is approaching an initial "finished" state that
Please note that to date, the driver has ONLY been tested on a Tropez
Plus. I would very much like to hear (and help out) people with Tropez
and Maui cards, since I think the driver can support those cards as
-well.
+well.
-Finally, the driver has not been tested as a static (non-modular) part
-of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux
-makes this rather unnecessary.
+Finally, the driver has not been tested (or even compiled) as a static
+(non-modular) part of the kernel. Alan Cox's good work in modularizing
+OSS/Free for Linux makes this rather unnecessary.
Some Questions
--------------
0) What does this driver do that the maui driver did not ?
**********************************************************************
-* can fully initialize a WaveFront card from cold boot - no DOS
+* can fully initialize a WaveFront card from cold boot - no DOS
utilities needed
* working patch/sample/program loading and unloading (the maui
driver didn't document how to make this work, and assumed
* for the Tropez Plus, (primitive) control of the YSS225 FX processor
* Virtual MIDI mode supported - 2 MIDI devices accessible via the
WaveFront's MPU401/UART emulation. One
- accesses the WaveFront synth, the other accesses the
- external MIDI connector. Full MIDI read/write semantics
- for both devices.
+ accesses the WaveFront synth, the other accesses the
+ external MIDI connector. Full MIDI read/write semantics
+ for both devices.
* OSS-compliant /dev/sequencer interface for the WaveFront synth,
- including native and GUS-format patch downloading.
+ including native and GUS-format patch downloading.
* semi-intelligent patch management (prototypical at this point)
-
**********************************************************************
1) What to do about MIDI interfaces ?
**********************************************************************
Either because its not finished yet, or because you're a better coder
than I am, or because you don't understand some aspect of how the card
-or the code works.
+or the code works.
I absolutely welcome comments, criticisms and suggestions about the
-design and implementation of the driver.
+design and implementation of the driver.
**********************************************************************
3) What files are included ?
**********************************************************************
drivers/sound/README.wavefront -- this file
- drivers/sound/wavefront.patch -- patches for the 2.1.106 sound driver
-s
- needed to make the rest of this work
+
+ drivers/sound/wavefront.patch -- patches for the 2.1.106 sound drivers
+ needed to make the rest of this work
+ DO NOT USE IF YOU'VE APPLIED THEM
+ BEFORE, OR HAVE 2.1.109 OR ABOVE
+
drivers/sound/wavfront.c -- the driver
drivers/sound/ys225.h -- data declarations for FX config
drivers/sound/ys225.c -- data definitions for FX config
- drivers/sound/wf_midi.c -- the "uart401" driver
- to support virtual MIDI mode.
+ drivers/sound/wf_midi.c -- the "uart401" driver
+ to support virtual MIDI mode.
include/wavefront.h -- the header file
Documentation/sound/Tropez+ -- short docs on configuration
PART TWO: apply the patches
+ DO THIS ONLY IF YOU HAVE A KERNEL VERSION BELOW 2.1.109
+ AND HAVE NOT ALREADY INSTALLED THE PATCH(ES).
+
cd drivers/sound
patch < wavefront.patch
cd <top of your kernel tree>
make xconfig (or whichever config option you use)
- - choose YES for Sound Support
+ - choose YES for Sound Support
- choose MODULE (M) for OSS Sound Modules
- - choose MODULE(M) to Generic OPL2/OPL3 support
- choose MODULE(M) to YM3812/OPL3 support
- - choose MODULE(M) for WaveFront support
- - choose MODULE(M) for CS4232 support
+ - choose MODULE(M) for WaveFront support
+ - choose MODULE(M) for CS4232 support
- - choose "N" for everything else (unless you have other
- soundcards you want support for)
+ - choose "N" for everything else (unless you have other
+ soundcards you want support for)
make dep
#undef CONFIG_SOUND_PAS
#undef CONFIG_SOUND_SB
#undef CONFIG_SOUND_ADLIB
-#define CONFIG_SOUND_ADLIB_MODULE 1
#undef CONFIG_SOUND_GUS
#undef CONFIG_SOUND_MPU401
#undef CONFIG_SOUND_PSS
alias char-major-14 wavefront
alias synth0 wavefront
alias mixer0 cs4232
+ alias audio0 cs4232
pre-install wavefront modprobe "-k" "cs4232"
- post-install wavefront modprobe "-k" "adlib_card"
+ post-install wavefront modprobe "-k" "opl3"
options wavefront io=0x200 irq=9
options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
- options adlib_card io=0x388
+ options opl3 io=0x388
-Things to note:
+Things to note:
the wavefront options "io" and "irq" ***MUST*** match the "synthio"
and "synthirq" cs4232 options.
- you can do without the adlib_card module if you don't
- want to use the OPL/[34] synth on the soundcard
+ you can do without the opl3 module if you don't
+ want to use the OPL/[34] FM synth on the soundcard
- the adlib_card io parameter is conventionally not adjustable.
+ the opl3 io parameter is conventionally not adjustable.
In theory, any not-in-use IO port address would work, but
just use 0x388 and stick with the crowd.
almost certainly have the firmware, and if not, its freely available
on their website, at:
- http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus
+ http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus
The file is called WFOS2001.MOT (for the Tropez+).
%%
^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext);
<<EOF>> { fputc ('\0', stdout); return; }
-\n {}
+\n {}
. {}
---- cut here -------------------------
shell> flex -ows.c ws.l
shell> cc -o ws ws.c
-
+
and then use it like this:
ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os
modprobe wavefront
-You should get something like this, directly if you're on a console, and in
-/var/log/messages:
+You should get something like this in /var/log/messages:
WaveFront: firmware 1.20 already loaded.
-or
+or
WaveFront: no response to firmware probe, assume raw.
Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
Config options: 0
-Installed drivers:
+Installed drivers:
-Card config:
+Card config:
Audio devices:
0: Crystal audio controller (CS4232) (DUPLEX)
hooked to the soundcard, you can use "-e" to route to the
external synth(s) (in theory, -D 1 should work as well, but I think
there is a bug in playmidi which prevents this from doing what it
-should).
+should).
**********************************************************************
8) What are the module parameters ?
Its best to read wavefront.c for this, but here is a summary:
-integers:
- wf_raw - if set, ignore apparent presence of firmware
- loaded onto the ICS2115, reset the whole
- board, and initialize it from scratch. (default = 0)
+integers:
+ wf_raw - if set, ignore apparent presence of firmware
+ loaded onto the ICS2115, reset the whole
+ board, and initialize it from scratch. (default = 0)
fx_raw - if set, always initialize the YSS225 processor
- on the Tropez plus. (default = 1)
+ on the Tropez plus. (default = 1)
< The next 4 are basically for kernel hackers to allow
- tweaking the driver for testing purposes. >
-
- wf_short_wait_count - loop counter used when waiting for
- status conditions on the board. This
- is CPU-specific. After this many
- loops, the driver will sleep.
- The default is 5000. I have a 66Mhz 486.
-
- wf_sleep_interval - the driver sleeps for
- HZ/wf_sleep_interval seconds per sleep.
- The default is 50.
-
- wf_sleep_tries - the number of times the driver will sleep
- when waiting for a status condition on the
- board. The default is 100 (2 secs, if
- wf_sleep_interval is 50).
-
- wf_debug_default - debugging flags. See sound/wavefront.h
- for WF_DEBUG_* values. Default is zero.
- Setting this allows you to debug the
- driver during module installation.
+ tweaking the driver for testing purposes. >
+
+ wait_usecs - loop timer used when waiting for
+ status conditions on the board.
+ The default is 150.
+
+ debug_default - debugging flags. See sound/wavefront.h
+ for WF_DEBUG_* values. Default is zero.
+ Setting this allows you to debug the
+ driver during module installation.
strings:
- wf_ospath - path to get to the pre-processed OS firmware.
- (default: /etc/sound/wavefront.os)
+ ospath - path to get to the pre-processed OS firmware.
+ (default: /etc/sound/wavefront.os)
**********************************************************************
9) Who should I contact if I have problems?
Just me: Paul Barton-Davis <pbd@op.net>
-
JOYSTICK DRIVER
P: Vojtech Pavlik
-M: vojtech@atrey.karlin.mff.cuni.cz
-W: http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/
+M: vojtech@ucw.cz
L: linux-joystick@atrey.karlin.mff.cuni.cz
+W: http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/
S: Maintained
KERNEL AUTOMOUNTER (AUTOFS)
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 115
+SUBLEVEL = 116
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
NM := nm -B
-ifdef CONFIG_CROSSCOMPILE
-# enable this for linking under OSF/1:
-LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
-else
- elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi)
- ifeq ($(elf),yes)
- LINKFLAGS = -static -T arch/alpha/vmlinux.lds
- else
- LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
- endif
-# GNU gcc/cc1/as can use pipes instead of temporary files
-CFLAGS := $(CFLAGS) -pipe
-endif
+LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
+CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
-CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8
+# Determine if we can use the BWX instructions with GAS.
+old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
-# determine if we can use the BWX instructions with GAS
-OLD_GAS := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
+# Determine if GCC understands the -mcpu= option.
+have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-# If PYXIS, then enable use of BWIO space
-ifneq ($(OLD_GAS),y)
- ifeq ($(CONFIG_ALPHA_PYXIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED
- endif
+# If GENERIC, make sure to turn off any instruction set extensions that
+# the host compiler might have on by default. Given that EV4 and EV5
+# have the same instruction set, prefer EV5 because an EV5 schedule is
+# more likely to keep an EV4 processor busy than vice-versa.
+ifeq ($(CONFIG_ALPHA_GENERIC)$(have_mcpu),yy)
+ CFLAGS := $(CFLAGS) -mcpu=ev5
endif
# If EV6, turn on the proper optimizations.
-ifeq ($(CONFIG_ALPHA_EV6),y)
- CFLAGS := -mcpu=ev6 $(CFLAGS)
+ifeq ($(CONFIG_ALPHA_EV6)$(have_mcpu),yy)
+ CFLAGS := $(CFLAGS) -mcpu=ev6
+endif
+
+# For TSUNAMI, we must have the assembler not emulate our instructions.
+# BWX is most important, but we don't really want any emulation ever.
+ifeq ($(old_gas),y)
+ ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI),)
+ # How do we do #error in make?
+ CFLAGS := --error-please-upgrade-your-assembler
+ endif
+else
+ ifeq ($(CONFIG_ALPHA_GENERIC),y)
+ CFLAGS := $(CFLAGS) -Wa,-mev6
+ endif
+ ifeq ($(CONFIG_ALPHA_PYXIS),y)
+ CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
+ endif
endif
HEAD := arch/alpha/kernel/head.o
@$(MAKEBOOT) rawboot
#
-# my boot writes directly to a specific disk partition, I doubt most
+# My boot writes directly to a specific disk partition, I doubt most
# people will want to do that without changes..
#
msb my-special-boot:
fi
choice 'Alpha system type' \
- "Avanti CONFIG_ALPHA_AVANTI \
- Alpha-XL CONFIG_ALPHA_XL \
- Alpha-XLT CONFIG_ALPHA_XLT \
- Cabriolet CONFIG_ALPHA_CABRIOLET \
- EB66 CONFIG_ALPHA_EB66 \
- EB66+ CONFIG_ALPHA_EB66P \
- EB64+ CONFIG_ALPHA_EB64P \
- EB164 CONFIG_ALPHA_EB164 \
- PC164 CONFIG_ALPHA_PC164 \
- LX164 CONFIG_ALPHA_LX164 \
- SX164 CONFIG_ALPHA_SX164 \
- DP264 CONFIG_ALPHA_DP264 \
- Jensen CONFIG_ALPHA_JENSEN \
- Noname CONFIG_ALPHA_NONAME \
- Takara CONFIG_ALPHA_TAKARA \
- Mikasa CONFIG_ALPHA_MIKASA \
- Noritake CONFIG_ALPHA_NORITAKE \
- Alcor CONFIG_ALPHA_ALCOR \
- Miata CONFIG_ALPHA_MIATA \
- Sable CONFIG_ALPHA_SABLE \
- Rawhide CONFIG_ALPHA_RAWHIDE \
- AlphaBook1 CONFIG_ALPHA_BOOK1 \
- Ruffian CONFIG_ALPHA_RUFFIAN \
- Platform2000 CONFIG_ALPHA_P2K" Cabriolet
+ "Generic CONFIG_ALPHA_GENERIC \
+ Alcor/Alpha-XLT CONFIG_ALPHA_ALCOR \
+ Alpha-XL CONFIG_ALPHA_XL \
+ AlphaBook1 CONFIG_ALPHA_BOOK1 \
+ Avanti CONFIG_ALPHA_AVANTI \
+ Cabriolet CONFIG_ALPHA_CABRIOLET \
+ DP264 CONFIG_ALPHA_DP264 \
+ EB164 CONFIG_ALPHA_EB164 \
+ EB64+ CONFIG_ALPHA_EB64P \
+ EB66 CONFIG_ALPHA_EB66 \
+ EB66+ CONFIG_ALPHA_EB66P \
+ Jensen CONFIG_ALPHA_JENSEN \
+ LX164 CONFIG_ALPHA_LX164 \
+ Miata CONFIG_ALPHA_MIATA \
+ Mikasa CONFIG_ALPHA_MIKASA \
+ Noname CONFIG_ALPHA_NONAME \
+ Noritake CONFIG_ALPHA_NORITAKE \
+ PC164 CONFIG_ALPHA_PC164 \
+ Platform2000 CONFIG_ALPHA_P2K \
+ Rawhide CONFIG_ALPHA_RAWHIDE \
+ Ruffian CONFIG_ALPHA_RUFFIAN \
+ SX164 CONFIG_ALPHA_SX164 \
+ Sable CONFIG_ALPHA_SABLE \
+ Takara CONFIG_ALPHA_TAKARA" Generic
# clear all implied options (don't want default values for those):
unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
+if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
+fi
if [ "$CONFIG_ALPHA_BOOK1" = "y" ]
then
define_bool CONFIG_ALPHA_NONAME y
# General setup
#
CONFIG_NATIVE=y
-# CONFIG_ALPHA_AVANTI is not set
+CONFIG_ALPHA_GENERIC=y
+# CONFIG_ALPHA_ALCOR is not set
# CONFIG_ALPHA_XL is not set
-# CONFIG_ALPHA_XLT is not set
+# CONFIG_ALPHA_BOOK1 is not set
+# CONFIG_ALPHA_AVANTI is not set
# CONFIG_ALPHA_CABRIOLET is not set
+# CONFIG_ALPHA_DP264 is not set
+# CONFIG_ALPHA_EB164 is not set
+# CONFIG_ALPHA_EB64P is not set
# CONFIG_ALPHA_EB66 is not set
# CONFIG_ALPHA_EB66P is not set
-# CONFIG_ALPHA_EB64P is not set
-# CONFIG_ALPHA_EB164 is not set
-# CONFIG_ALPHA_PC164 is not set
-# CONFIG_ALPHA_LX164 is not set
-# CONFIG_ALPHA_SX164 is not set
-# CONFIG_ALPHA_DP264 is not set
# CONFIG_ALPHA_JENSEN is not set
-# CONFIG_ALPHA_NONAME is not set
-# CONFIG_ALPHA_TAKARA is not set
+# CONFIG_ALPHA_LX164 is not set
+# CONFIG_ALPHA_MIATA is not set
# CONFIG_ALPHA_MIKASA is not set
+# CONFIG_ALPHA_NONAME is not set
# CONFIG_ALPHA_NORITAKE is not set
-CONFIG_ALPHA_ALCOR=y
-# CONFIG_ALPHA_MIATA is not set
-# CONFIG_ALPHA_SABLE is not set
+# CONFIG_ALPHA_PC164 is not set
+# CONFIG_ALPHA_P2K is not set
# CONFIG_ALPHA_RAWHIDE is not set
-# CONFIG_ALPHA_BOOK1 is not set
# CONFIG_ALPHA_RUFFIAN is not set
-# CONFIG_ALPHA_P2K is not set
+# CONFIG_ALPHA_SX164 is not set
+# CONFIG_ALPHA_SABLE is not set
+# CONFIG_ALPHA_TAKARA is not set
CONFIG_PCI=y
-CONFIG_ALPHA_EV5=y
-CONFIG_ALPHA_CIA=y
-CONFIG_ALPHA_SRM=y
-CONFIG_ALPHA_EISA=y
+CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
# CONFIG_PCI_QUIRKS is not set
CONFIG_PCI_OLD_PROC=y
CONFIG_NET=y
OX_OBJS := alpha_ksyms.o
+ifdef CONFIG_ALPHA_GENERIC
+
+O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \
+ core_t2.o core_tsunami.o \
+ sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \
+ sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
+ sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
+ sys_sx164.o sys_takara.o \
+ es1888.o smc37c669.o smc37c93x.o
+else
+
+# Core logic support
ifdef CONFIG_ALPHA_APECS
-O_OBJS += apecs.o
+O_OBJS += core_apecs.o
endif
ifdef CONFIG_ALPHA_CIA
-O_OBJS += cia.o
+O_OBJS += core_cia.o
endif
ifdef CONFIG_ALPHA_LCA
-O_OBJS += lca.o
+O_OBJS += core_lca.o
+endif
+ifdef CONFIG_ALPHA_MCPCIA
+O_OBJS += core_mcpcia.o
endif
ifdef CONFIG_ALPHA_PYXIS
-O_OBJS += pyxis.o
+O_OBJS += core_pyxis.o
endif
ifdef CONFIG_ALPHA_T2
-O_OBJS += t2.o
+O_OBJS += core_t2.o
endif
ifdef CONFIG_ALPHA_TSUNAMI
-O_OBJS += tsunami.o
+O_OBJS += core_tsunami.o
endif
-ifdef CONFIG_ALPHA_MCPCIA
-O_OBJS += mcpcia.o
+
+# Board support
+ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
+O_OBJS += sys_alcor.o
+endif
+ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
+O_OBJS += sys_cabriolet.o
+endif
+ifdef CONFIG_ALPHA_DP264
+O_OBJS += sys_dp264.o
+endif
+ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
+O_OBJS += sys_eb64p.o
+endif
+ifdef CONFIG_ALPHA_JENSEN
+O_OBJS += sys_jensen.o
+endif
+ifdef CONFIG_ALPHA_MIATA
+O_OBJS += sys_miata.o
+endif
+ifdef CONFIG_ALPHA_MIKASA
+O_OBJS += sys_mikasa.o
+endif
+ifdef CONFIG_ALPHA_NORITAKE
+O_OBJS += sys_noritake.o
+endif
+ifdef CONFIG_ALPHA_RAWHIDE
+O_OBJS += sys_rawhide.o
+endif
+ifdef CONFIG_ALPHA_RUFFIAN
+O_OBJS += sys_ruffian.o
+endif
+ifdef CONFIG_ALPHA_SABLE
+O_OBJS += sys_sable.o
+endif
+ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),)
+O_OBJS += sys_sio.o
+endif
+ifdef CONFIG_ALPHA_SX164
+O_OBJS += sys_sx164.o
+endif
+ifdef CONFIG_ALPHA_TAKARA
+O_OBJS += sys_takara.o
endif
-ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),nn)
-O_OBJS += smc37c93x.o
+# Device support
+ifdef CONFIG_ALPHA_MIATA
+O_OBJS += es1888.o
endif
-ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),nnn)
+ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
O_OBJS += smc37c669.o
endif
+ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),)
+O_OBJS += smc37c93x.o
+endif
+
+endif # GENERIC
ifdef SMP
O_OBJS += smp.o
all: kernel.o head.o
-head.o: head.s
-
-head.s: head.S $(TOPDIR)/include/asm-alpha/system.h
- $(CPP) -traditional $(AFLAGS) -o $*.s $<
-
include $(TOPDIR)/Rules.make
#include <asm/softirq.h>
#include <asm/fpu.h>
#include <asm/irq.h>
+#include <asm/machvec.h>
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
extern void __divqu (void);
extern void __remqu (void);
+EXPORT_SYMBOL(alpha_mv);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
#ifdef CONFIG_MATHEMU_MODULE
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
+extern long (*alpha_fp_emul) (unsigned long pc);
EXPORT_SYMBOL(alpha_fp_emul_imprecise);
+EXPORT_SYMBOL(alpha_fp_emul);
#endif
/*
+++ /dev/null
-/*
- * Code common to all APECS chips.
- *
- * Rewritten for Apecs from the lca.c from:
- *
- * Written by David Mosberger (davidm@cs.arizona.edu) with some code
- * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
- * bios code.
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef DEBUG
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#define vuip volatile unsigned int *
-
-static volatile unsigned int apecs_mcheck_expected = 0;
-static volatile unsigned int apecs_mcheck_taken = 0;
-static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
-unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the APECS_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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | | | | | | | | | | | | | | |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 haxr2 = 0; /* to keep gcc quiet */
-
-#ifdef CONFIG_ALPHA_SRM
- /* some SRMs step on these registers during a machine check: */
- register long s0 asm ("9");
- register long s1 asm ("10");
- register long s2 asm ("11");
- register long s3 asm ("12");
- register long s4 asm ("13");
- register long s5 asm ("14");
- asm volatile ("# %0" : "r="(s0));
- asm volatile ("# %0" : "r="(s1));
- asm volatile ("# %0" : "r="(s2));
- asm volatile ("# %0" : "r="(s3));
- asm volatile ("# %0" : "r="(s4));
- asm volatile ("# %0" : "r="(s5));
-#endif
-
- 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 = *(vuip)APECS_IOC_DCSR;
- *(vuip)APECS_IOC_DCSR = stat0;
- mb();
- DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
- /* if Type1 access, must set HAE #2 */
- if (type1) {
- haxr2 = *(vuip)APECS_IOC_HAXR2;
- mb();
- *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
- DBG(("conf_read: TYPE1 access\n"));
- }
-
- draina();
- apecs_mcheck_expected = 1;
- apecs_mcheck_taken = 0;
- mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
- if (apecs_mcheck_taken) {
- apecs_mcheck_taken = 0;
- value = 0xffffffffU;
- mb();
- }
- apecs_mcheck_expected = 0;
- mb();
-
-#if 1
- /*
- * 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.
- */
- draina();
-
- /* now look for any errors */
- stat0 = *(vuip)APECS_IOC_DCSR;
- DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
- if (stat0 & 0xffe0U) { /* is any error bit set? */
- /* if not NDEV, print status */
- if (!(stat0 & 0x0800)) {
- printk("apecs.c:conf_read: got stat0=%x\n", stat0);
- }
-
- /* reset error status: */
- *(vuip)APECS_IOC_DCSR = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
- value = 0xffffffff;
- }
-#endif
-
- /* if Type1 access, must reset HAE #2 so normal IO space ops work */
- if (type1) {
- *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
- mb();
- }
- restore_flags(flags);
-#ifdef CONFIG_ALPHA_SRM
- /* some SRMs step on these registers during a machine check: */
- asm volatile ("# %0" :: "r"(s0));
- asm volatile ("# %0" :: "r"(s1));
- asm volatile ("# %0" :: "r"(s2));
- asm volatile ("# %0" :: "r"(s3));
- asm volatile ("# %0" :: "r"(s4));
- asm volatile ("# %0" :: "r"(s5));
-#endif
- return value;
-}
-
-
-static void conf_write(unsigned long addr, unsigned int value, unsigned char type1)
-{
- unsigned long flags;
- unsigned int stat0;
- unsigned int haxr2 = 0; /* to keep gcc quiet */
-
- save_flags(flags); /* avoid getting hit by machine check */
- cli();
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)APECS_IOC_DCSR;
- *(vuip)APECS_IOC_DCSR = stat0;
- mb();
-
- /* if Type1 access, must set HAE #2 */
- if (type1) {
- haxr2 = *(vuip)APECS_IOC_HAXR2;
- mb();
- *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
- }
-
- draina();
- apecs_mcheck_expected = 1;
- mb();
- /* access configuration space: */
- *(vuip)addr = value;
- mb();
- mb(); /* magic */
- apecs_mcheck_expected = 0;
- mb();
-
-#if 1
- /*
- * 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.
- */
- draina();
-
- /* now look for any errors */
- stat0 = *(vuip)APECS_IOC_DCSR;
- if (stat0 & 0xffe0U) { /* is any error bit set? */
- /* if not NDEV, print status */
- if (!(stat0 & 0x0800)) {
- printk("apecs.c:conf_write: got stat0=%x\n", stat0);
- }
-
- /* reset error status: */
- *(vuip)APECS_IOC_DCSR = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
- }
-#endif
-
- /* if Type1 access, must reset HAE #2 so normal IO space ops work */
- if (type1) {
- *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
- mb();
- }
- restore_flags(flags);
-}
-
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr = APECS_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 = APECS_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 = APECS_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 = APECS_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 = APECS_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 = APECS_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 apecs_init(unsigned long mem_start, unsigned long mem_end)
-{
-
-#ifdef CONFIG_ALPHA_XL
- /*
- * Set up the PCI->physical memory translation windows.
- * For the XL we *must* use both windows, in order to
- * maximize the amount of physical memory that can be used
- * to DMA from the ISA bus, and still allow PCI bus devices
- * access to all of host memory.
- *
- * see <asm/apecs.h> for window bases and sizes.
- *
- * this restriction due to the true XL motherboards' 82379AB SIO
- * PCI<->ISA bridge chip which passes only 27 bits of address...
- */
-
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
-
- *(vuip)APECS_IOC_PB2R = 1U<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB2R = 0;
-
-#else /* CONFIG_ALPHA_XL */
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 1 for enabled and mapped to 0 */
- if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) && (*(vuip)APECS_IOC_TB1R == 0))
- {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 0
- printk("apecs_init: using Window 1 settings\n");
- printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
- *(vuip)APECS_IOC_PB1R,
- *(vuip)APECS_IOC_PM1R,
- *(vuip)APECS_IOC_TB1R);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) && (*(vuip)APECS_IOC_TB2R == 0))
- {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 0
- printk("apecs_init: using Window 2 settings\n");
- printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
- *(vuip)APECS_IOC_PB2R,
- *(vuip)APECS_IOC_PM2R,
- *(vuip)APECS_IOC_TB2R);
-#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
- *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
-
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
- }
-#endif /* CONFIG_ALPHA_XL */
-
-#ifdef CONFIG_ALPHA_CABRIOLET
-#ifdef NO_LONGER_NEEDED_I_HOPE
- /*
- * JAE: HACK!!! for now, hardwire if configured...
- * davidm: Older miniloader versions don't set the clock frequency
- * right, so hardcode it for now.
- */
- if (hwrpb->sys_type == ST_DEC_EB64P) {
- hwrpb->sys_type = ST_DEC_EBPC64;
- }
- if (hwrpb->cycle_freq == 0) {
- hwrpb->cycle_freq = 275000000;
- }
-
- /* update checksum: */
- {
- unsigned long *l, sum;
-
- sum = 0;
- for (l = (unsigned long *) hwrpb;
- l < (unsigned long *) &hwrpb->chksum;
- ++l)
- sum += *l;
- hwrpb->chksum = sum;
- }
-#endif /* NO_LONGER_NEEDED_I_HOPE */
-#endif /* CONFIG_ALPHA_CABRIOLET */
-
- /*
- * Finally, clear the HAXR2 register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
-#if 0
- unsigned int haxr2 = *(vuip)APECS_IOC_HAXR2; mb();
- if (haxr2) printk("apecs_init: HAXR2 was 0x%x\n", haxr2);
-#endif
- *(vuip)APECS_IOC_HAXR2 = 0; mb();
- }
-
-
- return mem_start;
-}
-
-int apecs_pci_clr_err(void)
-{
- apecs_jd = *(vuip)APECS_IOC_DCSR;
- if (apecs_jd & 0xffe0L) {
- apecs_jd1 = *(vuip)APECS_IOC_SEAR;
- *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L;
- apecs_jd = *(vuip)APECS_IOC_DCSR;
- mb();
- }
- *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
- apecs_jd2 = *(vuip)APECS_IOC_TBIA;
- mb();
- return 0;
-}
-
-void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- struct el_common *mchk_header;
- struct el_procdata *mchk_procdata;
- struct el_apecs_sysdata_mcheck *mchk_sysdata;
- unsigned long *ptr;
- int i;
-
-
- mchk_header = (struct el_common *)la_ptr;
- mchk_procdata = (struct el_procdata *)
- (la_ptr + mchk_header->proc_offset - sizeof(mchk_procdata->paltemp));
- mchk_sysdata =
- (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
-
-#ifdef DEBUG
- printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(" 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);
- printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
- 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.
- */
-#ifdef CONFIG_ALPHA_MIKASA
-#define MCHK_NO_DEVSEL 0x205L
-#define MCHK_NO_TABT 0x204L
- if (apecs_mcheck_expected &&
- (((unsigned int)mchk_header->code == MCHK_NO_DEVSEL) ||
- ((unsigned int)mchk_header->code == MCHK_NO_TABT))
- )
- {
-#else
- if (apecs_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) {
-#endif
- apecs_mcheck_expected = 0;
- apecs_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- apecs_pci_clr_err();
- wrmces(0x7);
- mb();
- draina();
- DBG(("apecs_machine_check: EXPECTED\n"));
- }
- else if (vector == 0x620 || vector == 0x630) {
- wrmces(0x1f); /* disable correctable from now on */
- mb();
- draina();
- printk("apecs_machine_check: HW correctable (0x%lx)\n",
- vector);
- }
- else {
- printk(KERN_CRIT "APECS machine check:\n");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(KERN_CRIT
- " 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);
- printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%lx %lx %lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#if 0
- /* doesn't work with MILO */
- show_regs(regs);
-#endif
- }
-}
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
+#include <asm/pci.h>
#include <asm/dma.h>
-#if 0
+#include "proto.h"
+#include "bios32.h"
+
+#define DEBUG_DEVS 0
+
+#if DEBUG_DEVS
# define DBG_DEVS(args) printk args
#else
# define DBG_DEVS(args)
asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
+void reset_for_srm(void) { }
#else /* CONFIG_PCI */
#include <linux/malloc.h>
#include <linux/mm.h>
-#include <asm/hwrpb.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/system.h>
-
-#define KB 1024
-#define MB (1024*KB)
-#define GB (1024*MB)
+/*
+ * PCI public interfaces.
+ */
#define MAJOR_REV 0
+#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */
-/* minor revision 4, add multi-PCI handling */
-#define MINOR_REV 4
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+int
+pcibios_present(void)
+{
+ return alpha_mv.pci_read_config_byte != NULL;
+}
+void __init
+pcibios_init(void)
+{
+ printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+ if (alpha_use_srm_setup)
+ printk(" NOT modifying existing (SRM) PCI configuration\n");
-/*
- * On multiple PCI bus machines, create a handle from the bus number.
- */
-#if defined(CONFIG_ALPHA_MCPCIA) /* || defined(CONFIG_ALPHA_TSUNAMI) */
-extern struct linux_hose_info *bus2hose[256];
-#define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32)
-#define DEV_IS_ON_PRIMARY(dev) \
- (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
-#else
-#define HANDLE(b) (0)
-#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0)
-#endif
+ /* FIXME: Scan for multiple PCI busses here. */
+}
-/*
- * PCI_MODIFY
- *
- * Temporary internal macro. If this 0, then do not write to any of
- * the PCI registers, merely read them (i.e., use configuration as
- * determined by SRM). The SRM seem do be doing a less than perfect
- * job in configuring PCI devices, so for now we do it ourselves.
- * Reconfiguring PCI devices breaks console (RPB) callbacks, but
- * those don't work properly with 64 bit addresses anyways.
- *
- * The accepted convention seems to be that the console (POST
- * software) should fully configure boot devices and configure the
- * interrupt routing of *all* devices. In particular, the base
- * addresses of non-boot devices need not be initialized. For
- * example, on the AXPpci33 board, the base address a #9 GXE PCI
- * graphics card reads as zero (this may, however, be due to a bug in
- * the graphics card---there have been some rumor that the #9 BIOS
- * incorrectly resets that address to 0...).
- */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-#define PCI_MODIFY 0
-static struct pci_dev *irq_dev_to_reset[16];
-static unsigned char irq_to_reset[16];
-static int irq_reset_count = 0;
-static struct pci_dev *io_dev_to_reset[16];
-static unsigned char io_reg_to_reset[16];
-static unsigned int io_to_reset[16];
-static int io_reset_count = 0;
-#else /* SRM_SETUP */
-#define PCI_MODIFY 1
-#endif /* SRM_SETUP */
-
-extern struct hwrpb_struct *hwrpb;
-
-/* Forward declarations for some extra fixup routines for specific hardware. */
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-extern int SMC93x_Init(void);
-#endif
-extern int SMC669_Init(void);
-#ifdef CONFIG_ALPHA_MIATA
-static int es1888_init(void);
-#endif
+char * __init
+pcibios_setup(char *str)
+{
+ return str;
+}
+
+void __init
+pcibios_fixup(void)
+{
+ alpha_mv.pci_fixup();
+}
-#if PCI_MODIFY
+void __init
+pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+int
+pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_byte)
+ r = alpha_mv.pci_read_config_byte(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_word)
+ r = alpha_mv.pci_read_config_word(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_dword)
+ r = alpha_mv.pci_read_config_dword(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_byte)
+ r = alpha_mv.pci_write_config_byte(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_word)
+ r = alpha_mv.pci_write_config_word(bus, dev, where, value);
+ return r;
+}
+
+int
+pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_dword)
+ r = alpha_mv.pci_write_config_dword(bus, dev, where, value);
+ return r;
+}
+
+asmlinkage int
+sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ubyte = 0xff;
+ put_user(ubyte, buf);
+ break;
+ case 2:
+ err = pcibios_read_config_word(bus, dfn, off, &ushort);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ushort = 0xffff;
+ put_user(ushort, (unsigned short *)buf);
+ break;
+ case 4:
+ err = pcibios_read_config_dword(bus, dfn, off, &uint);
+ if (err != PCIBIOS_SUCCESSFUL)
+ uint = 0xffffffff;
+ put_user(uint, (unsigned int *)buf);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
+
+asmlinkage int
+sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = get_user(ubyte, buf);
+ if (err)
+ break;
+ err = pcibios_write_config_byte(bus, dfn, off, ubyte);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 2:
+ err = get_user(ushort, (unsigned short *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_word(bus, dfn, off, ushort);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 4:
+ err = get_user(uint, (unsigned int *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_dword(bus, dfn, off, uint);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
-/*
- * NOTE: we can't just blindly use 64K for machines with EISA busses; they
- * may also have PCI-PCI bridges present, and then we'd configure the bridge
- * incorrectly.
- *
- * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
- * IO space areas allocated *before* 0xC000; this is because certain
- * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
- * accesses to probe the bus. If a device's registers appear at 0xC000,
- * it may see an INx/OUTx at that address during BIOS emulation of the
- * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
- *
- * Note that we may need this stuff for SRM_SETUP also, since certain
- * SRM consoles screw up and allocate I/O space addresses > 64K behind
- * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, AFAIK.
- */
-#if defined(CONFIG_ALPHA_EISA)
-#define DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
-#else
-#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
-#endif
-static unsigned int io_base;
-#if defined(CONFIG_ALPHA_XL)
/*
- * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
- * that get passed through the PCI<->ISA bridge chip. Although this causes
- * us to set the PCI->Mem window bases lower than normal, we still allocate
- * PCI bus devices' memory addresses *below* the low DMA mapping window,
- * and hope they fit below 64Mb (to avoid conflicts), and so that they can
- * be accessed via SPARSE space.
- *
- * We accept the risk that a broken Myrinet card will be put into a true XL
- * and thus can more easily run into the problem described below.
+ * Gory details start here...
*/
-#define DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
-#elif defined(CONFIG_ALPHA_LCA) || defined(CONFIG_ALPHA_APECS)
+struct linux_hose_info *bus2hose[256];
+
/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * However, APECS and LCA have only 34 bits for physical addresses, thus
- * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ * Align VAL to ALIGN, which must be a power of two.
*/
-#define DEFAULT_MEM_BASE (64*MB + 2*MB)
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
-#else
-/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * Because CIA and PYXIS and T2 have more bits for physical addresses,
- * they support an expanded range of SPARSE memory addresses.
+
+/*
+ * The following structure records initial configuration of devices
+ * so that we can reset them on shutdown and so enable clean reboots
+ * on SRM. It is more trouble than it iw worth to conditionalize this.
*/
-#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+static struct {
+ struct reset_irq {
+ struct pci_dev *dev;
+ u8 irq;
+ } irq[16];
+ int irq_count;
+
+ struct reset_io {
+ struct pci_dev *dev;
+ u8 reg;
+ u32 io;
+ } io[16];
+ int io_count;
+} srm_resets;
+
+/* Apply the collected reset modifications. */
+
+void
+reset_for_srm(void)
+{
+ struct pci_dev *dev;
+ int i;
+
+ /* Reset any IRQs that we changed. */
+ for (i = 0; i < srm_resets.irq_count; i++) {
+ dev = srm_resets.irq[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE,
+ srm_resets.irq[i].irq);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IRQ 0x%x changed back from 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.irq[i].irq, dev->irq);
#endif
-static unsigned int mem_base;
+ }
+
+ /* Reset any IO addresses that we changed. */
+ for (i = 0; i < srm_resets.io_count; i++) {
+ dev = srm_resets.io[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ srm_resets.io[i].reg,
+ srm_resets.io[i].io);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IO restored to 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.io[i].io);
+#endif
+ }
+}
+
/*
* Disable PCI device DEV so that it does not respond to I/O or memory
* accesses.
*/
-static void disable_dev(struct pci_dev *dev)
+static void __init
+disable_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("disable_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("disable_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
* console code to do the right thing, and ignore it here... :-\
*/
return;
}
+#if DEBUG_DEVS && 0
+ /* Worse HACK: Don't disable the video card, so I can see where
+ it is *really* falling over. */
+ if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
+ DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n",
+ dev->vendor, dev->device));
+ return;
+ }
+#endif
+
+ DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
+ dev->vendor, dev->device));
+
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
*/
#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-static void layout_dev(struct pci_dev *dev)
+static unsigned int io_base;
+static unsigned int mem_base;
+
+static void __init
+layout_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("layout_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("layout_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
* console code to do the right thing, and ignore it here... :-\
*/
pcibios_write_config_dword(bus->number, dev->devfn,
off, base | 0x1);
- handle = HANDLE(bus->number) | base | 1;
+ handle = PCI_HANDLE(bus->number) | base | 1;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
mem_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
off, base);
- handle = HANDLE(bus->number) | base;
+ handle = PCI_HANDLE(bus->number) | base;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
dev->device, handle, size));
dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
}
-
-static int layout_bus(struct pci_bus *bus)
+static int __init
+layout_bus(struct pci_bus *bus)
{
unsigned int l, tio, bio, tmem, bmem;
struct pci_bus *child;
return found_vga;
}
-#endif /* !PCI_MODIFY */
-
-
-int pcibios_present(void)
+void __init
+layout_all_busses(unsigned long default_io_base,
+ unsigned long default_mem_base)
{
- return 1;
-}
+ struct pci_bus *cur;
+#if defined(CONFIG_ALPHA_GENERIC)
+ static struct linux_hose_info dummy_hose;
+ int i;
-void __init
-pcibios_init(void)
-{
- printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
-#if !PCI_MODIFY
- printk("...NOT modifying existing (SRM) PCI configuration\n");
+ /*
+ * HACK: Emulate a multi-bus machine to a limited extent
+ * by initializing bus2hose to point to something that
+ * has pci_hose_index & pci_first_busno zero.
+ */
+ for (i = 0; i <= 0xff; i++)
+ bus2hose[i] = &dummy_hose;
#endif
+
+ /*
+ * Scan the tree, allocating PCI memory and I/O space.
+ */
+ /*
+ * Sigh; check_region() will need changing to accept a PCI_HANDLE,
+ * if we allocate I/O space addresses on a per-bus basis.
+ * For now, make the I/O bases unique across all busses, so
+ * that check_region() will not get confused... ;-}
+ */
+ io_base = default_io_base;
+ for (cur = &pci_root; cur; cur = cur->next) {
+ mem_base = default_mem_base;
+ DBG_DEVS(("layout_all_busses: calling layout_bus()\n"));
+ layout_bus(cur);
+ }
+ DBG_DEVS(("layout_all_busses: done.\n"));
}
+
/*
* The SRM console *disables* the IDE interface, this code ensures it's
* enabled.
* written twice (I believe this is a safety feature to prevent
* accidental modification---fun, isn't it?).
*/
-static inline void enable_ide(long ide_base)
+
+void __init
+enable_ide(long ide_base)
{
int data;
outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
}
-/*
- * A small note about bridges and interrupts. The DECchip 21050 (and later)
- * adheres to the PCI-PCI bridge specification. This says that the
- * interrupts on the other side of a bridge are swizzled in the following
- * manner:
- *
- * Dev Interrupt Interrupt
- * Pin on Pin on
- * Device Connector
- *
- * 4 A A
- * B B
- * C C
- * D D
- *
- * 5 A B
- * B C
- * C D
- * D A
- *
- * 6 A C
- * B D
- * C A
- * D B
- *
- * 7 A D
- * B A
- * C B
- * D C
- *
- * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
- * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
- *
- * The following code is somewhat simplistic as it assumes only one bridge.
- * I will fix it later (david.rusling@reo.mts.dec.com).
- */
-static inline unsigned char
-bridge_swizzle(unsigned char pin, unsigned int slot)
-{
- /* swizzle */
- return (((pin-1) + slot) % 4) + 1;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* look for mis-configured devices' I/O space addresses behind bridges */
-static void check_behind_io(struct pci_dev *dev)
+/* Look for mis-configured devices' I/O space addresses behind bridges. */
+static void
+check_behind_io(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
unsigned int reg, orig_base, new_base, found_one = 0;
+ struct reset_io *ior;
for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
- /* read the current setting, check for I/O space and >= 64K */
- pcibios_read_config_dword(bus->number, dev->devfn, reg, &orig_base);
+ /* Read the current setting, check for I/O space and >= 64K */
+ pcibios_read_config_dword(bus->number, dev->devfn,
+ reg, &orig_base);
+
if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO))
continue; /* unused or non-IO */
+
if (orig_base < 64*1024) {
#if 1
printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n",
bus->number, PCI_SLOT(dev->devfn), orig_base);
#endif
if (orig_base & ~1)
- continue; /* OK! */
+ continue; /* OK! */
orig_base = 0x12001; /* HACK! FIXME!! */
}
pcibios_write_config_dword(bus->number, dev->devfn,
reg, new_base);
- io_dev_to_reset[io_reset_count] = dev;
- io_reg_to_reset[io_reset_count] = reg;
- io_to_reset[io_reset_count] = orig_base;
- io_reset_count++;
+ ior = &srm_resets.io[srm_resets.io_count++];
+ ior->dev = dev;
+ ior->reg = reg;
+ ior->io = orig_base;
found_one++;
- } /* end for-loop */
+ }
- /* if any were modified, gotta hack the bridge IO limits too... */
+ /* If any were modified, gotta hack the bridge IO limits too. */
if (found_one) {
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
- unsigned int l;
- /*
- * Set up the top and bottom of the PCI I/O segment
- * for this bus.
- */
- pcibios_read_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, &l);
+ if (bus->self) {
+ struct pci_dev *bridge = bus->self;
+ unsigned int l;
+ /*
+ * Set up the top and bottom of the PCI I/O segment
+ * for this bus.
+ */
+ pcibios_read_config_dword(bridge->bus->number,
+ bridge->devfn, 0x1c, &l);
#if 1
printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n",
bus->number, PCI_SLOT(bridge->devfn), l);
#endif
- l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, l);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x3c, 0x00040000);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x4, 0xffff0007);
- } else
- printk("check_behind_io: WARNING! bus->self NULL\n");
+ l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn, 0x1c, l);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x3c, 0x00040000);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x4, 0xffff0007);
+ } else
+ printk("check_behind_io: WARNING! bus->self NULL\n");
}
}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
+
/*
- * Most evaluation boards share most of the fixup code, which is isolated
- * here. This function is declared "inline" as only one platform will ever
- * be selected in any given kernel. If that platform doesn't need this code,
- * we don't want it around as dead code.
+ * Most boards share most of the fixup code, which is isolated here.
*/
-static inline void
-common_fixup(long min_idsel, long max_idsel, long irqs_per_slot,
- char irq_tab[max_idsel - min_idsel + 1][irqs_per_slot],
- long ide_base)
+
+void __init
+common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
+ int (*swizzle)(struct pci_dev *dev, int *pin))
{
- struct pci_dev *dev, *curr;
- unsigned char pin;
- unsigned char slot;
+ struct pci_dev *dev;
+ u8 pin, slot, irq_orig;
+ int irq;
/*
- * Go through all devices, fixing up irqs as we see fit:
+ * Go through all devices, fixing up irqs as we see fit.
*/
for (dev = pci_devices; dev; dev = dev->next) {
- if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE ||
- dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA) {
- /*
- * HACK: the PCI-to-EISA bridge appears not to identify
- * itself as a bridge... :-(
- */
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82375) {
- DBG_DEVS(("common_fixup: ignoring PCEB...\n"));
- continue;
- }
+ if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
+ (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
+ continue;
- /*
- * This device is not on the primary bus, we need
- * to figure out which interrupt pin it will come
- * in on. We know which slot it will come in on
- * 'cos that slot is where the bridge is. Each
- * time the interrupt line passes through a PCI-PCI
- * bridge we must apply the swizzle function (see
- * the inline static routine above).
- */
- dev->irq = 0;
- if (!DEV_IS_ON_PRIMARY(dev)) {
- /* read the pin and do the PCI-PCI bridge
- interrupt pin swizzle */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
- /* cope with 0 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- /* follow the chain of bridges, swizzling
- as we go */
- curr = dev;
-#if defined(CONFIG_ALPHA_MIATA)
- /* check first for the built-in bridge */
- if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
- (PCI_SLOT(dev->bus->self->devfn) == 20)) {
- slot = PCI_SLOT(dev->devfn) + 5;
- DBG_DEVS(("MIATA: bus 1 slot %d pin %d"
- " irq %d min_idsel %d\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if ((PCI_SLOT(curr->bus->self->devfn) == 8) ||
- (PCI_SLOT(curr->bus->self->devfn) == 20))
- {
- slot = PCI_SLOT(curr->devfn) + 5;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#elif defined(CONFIG_ALPHA_NORITAKE)
- /* check first for the built-in bridge */
- if (PCI_SLOT(dev->bus->self->devfn) == 8) {
- slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
- DBG_DEVS(("NORITAKE: bus 1 slot %d pin %d"
- "irq %d min_idsel %ld\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if (PCI_SLOT(curr->bus->self->devfn) == 8) {
- slot = PCI_SLOT(curr->devfn) + 15;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#else /* everyone but MIATA and NORITAKE */
- DBG_DEVS(("common_fixup: bus %d slot %d pin %d "
- "irq %d min_idsel %ld\n",
- curr->bus->number,
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- do {
- /* swizzle */
- pin =
- bridge_swizzle(pin, PCI_SLOT(curr->devfn));
- /* move up the chain of bridges */
- curr = curr->bus->self;
- } while (curr->bus->self);
- /* The slot is the slot of the last bridge. */
- slot = PCI_SLOT(curr->devfn);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * must make sure that SRM didn't screw up
- * and allocate an address > 64K for I/O
- * space behind a PCI-PCI bridge
- */
- check_behind_io(dev);
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- } else { /* just a device on a primary bus */
- /* work out the slot */
- slot = PCI_SLOT(dev->devfn);
- /* read the pin */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
- DBG_DEVS(("common_fixup: bus %d slot %d"
- " pin %d irq %d min_idsel %ld\n",
- dev->bus->number, slot, pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- /* cope with 0 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- }
- if (irq_tab[slot - min_idsel][pin] != -1)
- dev->irq = irq_tab[slot - min_idsel][pin];
-#ifdef CONFIG_ALPHA_RAWHIDE
- dev->irq +=
- 24 * bus2hose[dev->bus->number]->pci_hose_index;
-#endif /* RAWHIDE */
-#ifdef CONFIG_ALPHA_SRM
- {
- unsigned char irq_orig;
- /* read the original SRM-set IRQ and tell */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_LINE,
- &irq_orig);
- if (irq_orig != dev->irq) {
- DBG_DEVS(("common_fixup: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed to 0x%x\n",
- dev->bus->number,PCI_SLOT(dev->devfn),
- irq_orig, dev->irq));
-#ifdef CONFIG_ALPHA_SRM_SETUP
- irq_dev_to_reset[irq_reset_count] = dev;
- irq_to_reset[irq_reset_count] = irq_orig;
- irq_reset_count++;
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- }
- }
-#endif /* SRM */
-
- /* always tell the device, so the driver knows what is
- * the real IRQ to use; the device does not use it.
- */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-
- DBG_DEVS(("common_fixup: bus %d slot 0x%x"
- " VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x"
- " pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- dev->vendor, dev->device,
- slot, pin, dev->irq));
-
- /*
- * if it's a VGA, enable its BIOS ROM at C0000
- */
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
- if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
- (dev->device >= 0x00a0) &&
- (dev->device <= 0x00ac)) {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x00000000);
- } else {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- /*
- * if it's a SCSI, disable its BIOS ROM
- */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
- pcibios_write_config_dword(dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x0000000);
- }
- }
- }
- if (ide_base) {
- enable_ide(ide_base);
- }
-}
-
-/*
- * The EB66+ is very similar to the EB66 except that it does not have
- * the on-board NCR and Tulip chips. In the code below, I have used
- * slot number to refer to the id select line and *not* the slot
- * number used in the EB66+ documentation. However, in the table,
- * I've given the slot number, the id select line and the Jxx number
- * that's printed on the board. The interrupt pins from the PCI slots
- * are wired into 3 interrupt summary registers at 0x804, 0x805 and
- * 0x806 ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void eb66p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
- {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
- {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
- };
- common_fixup(6, 10, 5, irq_tab, 0x398);
-}
-
-
-/*
- * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
- * PCI slots, the SIO, PCI/IDE, and USB.
- *
- * Each of the interrupts can be individually masked. This is
- * accomplished by setting the appropriate bit in the mask register.
- * A bit is set by writing a "1" to the desired position in the mask
- * register and cleared by writing a "0". There are 3 mask registers
- * located at ISA address 804h, 805h and 806h.
- *
- * An I/O read at ISA address 804h, 805h, 806h will return the
- * state of the 11 PCI interrupts and not the state of the MASKED
- * interrupts.
- *
- * Note: A write to I/O 804h, 805h, and 806h the mask register will be
- * updated.
- *
- *
- * ISA DATA<7:0>
- * ISA +--------------------------------------------------------------+
- * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- * +==============================================================+
- * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
- * +--------------------------------------------------------------+
- * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
- * +--------------------------------------------------------------+
- * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
- * +--------------------------------------------------------------+
- * * Rsrv = reserved bits
- * Note: The mask register is write-only.
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Saturn I/O
- * 9 32 bit PCI option slot 3
- * 10 USB
- * 11 IDE
- *
- */
-
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-static inline void alphapc164_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
- { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
- { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
- { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
- { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
- };
-
- common_fixup(5, 11, 5, irq_tab, 0);
- SMC93x_Init();
-}
-#endif
-
-/*
- * The AlphaPC64 is very similar to the EB66+ except that its slots
- * are numbered differently. In the code below, I have used slot
- * number to refer to the id select line and *not* the slot number
- * used in the AlphaPC64 documentation. However, in the table, I've
- * given the slot number, the id select line and the Jxx number that's
- * printed on the board. The interrupt pins from the PCI slots are
- * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
- * ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void cabriolet_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
- { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
- { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
- };
-
- common_fixup(5, 9, 5, irq_tab, 0x398);
-}
-
-
-/*
- * Fixup configuration for EB66/EB64+ boards.
- *
- * Both these boards use the same interrupt summary scheme. There are
- * two 8 bit external summary registers as follows:
- *
- * Summary @ 0x26:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line A from slot 1
- * 2 Interrupt Line B from slot 0
- * 3 Interrupt Line B from slot 1
- * 4 Interrupt Line C from slot 0
- * 5 Interrupt line from the two ISA PICs
- * 6 Tulip (slot
- * 7 NCR SCSI
- *
- * Summary @ 0x27
- * Bit Meaning
- * 0 Interrupt Line C from slot 1
- * 1 Interrupt Line D from slot 0
- * 2 Interrupt Line D from slot 1
- * 3 RAZ
- * 4 RAZ
- * 5 RAZ
- * 6 RAZ
- * 7 RAZ
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 5 NCR SCSI controller
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 Intel SIO PCI-ISA bridge chip
- * 9 Tulip - DECchip 21040 Ethernet controller
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void eb66_and_eb64p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
- {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
- {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
-}
-
-
-/*
- * Fixup configuration for MIKASA (AlphaServer 1000)
- *
- * Summary @ 0x536:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line B from slot 0
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 2
- * 9 Interrupt Line B from slot 2
- *10 Interrupt Line C from slot 2
- *11 Interrupt Line D from slot 2
- *12 NCR 810 SCSI
- *13 Power Supply Fail
- *14 Temperature Warn
- *15 Reserved
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 NCR SCSI controller
- * 7 Intel PCI-EISA bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void mikasa_fixup(void)
-{
- static char irq_tab[8][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
- };
- common_fixup(6, 13, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for NORITAKE (AlphaServer 1000A)
- *
- * This is also used for CORELLE (AlphaServer 800)
- * and ALCOR Primo (AlphaStation 600A).
- *
- * Summary @ 0x542, summary register #1:
- * Bit Meaning
- * 0 All valid ints from summary regs 2 & 3
- * 1 QLOGIC ISP1020A SCSI
- * 2 Interrupt Line A from slot 0
- * 3 Interrupt Line B from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line A from slot 2
- * 7 Interrupt Line B from slot 2
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line B from slot 3
- *10 Interrupt Line A from slot 4
- *11 Interrupt Line B from slot 4
- *12 Interrupt Line A from slot 5
- *13 Interrupt Line B from slot 5
- *14 Interrupt Line A from slot 6
- *15 Interrupt Line B from slot 6
- *
- * Summary @ 0x544, summary register #2:
- * Bit Meaning
- * 0 OR of all unmasked ints in SR #2
- * 1 OR of secondary bus ints
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line C from slot 1
- * 5 Interrupt line D from slot 1
- * 6 Interrupt Line C from slot 2
- * 7 Interrupt Line D from slot 2
- * 8 Interrupt Line C from slot 3
- * 9 Interrupt Line D from slot 3
- *10 Interrupt Line C from slot 4
- *11 Interrupt Line D from slot 4
- *12 Interrupt Line C from slot 5
- *13 Interrupt Line D from slot 5
- *14 Interrupt Line C from slot 6
- *15 Interrupt Line D from slot 6
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 7 Intel PCI-EISA bridge chip
- * 8 DEC PCI-PCI bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void noritake_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSELs 16, 17, and 25 are CORELLE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
- { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
- /* the following 5 are actually on PCI bus 1, which is */
- /* across the built-in bridge of the NORITAKE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
- {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
- {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
- {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
- };
- common_fixup(5, 19, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALCOR and XLT (XL-300/366/433)
- *
- * Summary @ GRU_INT_REQ:
- * Bit Meaning
- * 0 Interrupt Line A from slot 2
- * 1 Interrupt Line B from slot 2
- * 2 Interrupt Line C from slot 2
- * 3 Interrupt Line D from slot 2
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 0
- * 9 Interrupt Line B from slot 0
- *10 Interrupt Line C from slot 0
- *11 Interrupt Line D from slot 0
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line D from slot 3
- *17 Interrupt Line D from slot 3
- *18 Interrupt Line D from slot 3
- *19 Interrupt Line D from slot 3
- *20-30 Reserved
- *31 EISA interrupt
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 built-in TULIP (XLT only)
- * 7 PCI on board slot 0
- * 8 PCI on board slot 3
- * 9 PCI on board slot 4
- * 10 PCEB (PCI-EISA bridge)
- * 11 PCI on board slot 2
- * 12 PCI on board slot 1
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void alcor_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSEL 17 is XLT only */
- {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
- { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- };
- common_fixup(6, 12, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
- *
- * Summary Registers (536/53a/53c):
- * Bit Meaning
- *-----------------
- * 0 PCI slot 0
- * 1 NCR810 (builtin)
- * 2 TULIP (builtin)
- * 3 mouse
- * 4 PCI slot 1
- * 5 PCI slot 2
- * 6 keyboard
- * 7 floppy
- * 8 COM2
- * 9 parallel port
- *10 EISA irq 3
- *11 EISA irq 4
- *12 EISA irq 5
- *13 EISA irq 6
- *14 EISA irq 7
- *15 COM1
- *16 EISA irq 9
- *17 EISA irq 10
- *18 EISA irq 11
- *19 EISA irq 12
- *20 EISA irq 13
- *21 EISA irq 14
- *22 NC
- *23 IIC
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 0 TULIP
- * 1 SCSI
- * 2 PCI-EISA bridge
- * 3 none
- * 4 none
- * 5 none
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-/*
- * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
- * with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables
- * in irq.c
- */
-static inline void sable_fixup(void)
-{
- static char irq_tab[9][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
- { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
- { -1, -1, -1, -1, -1}, /* IdSel 3, none */
- { -1, -1, -1, -1, -1}, /* IdSel 4, none */
- { -1, -1, -1, -1, -1}, /* IdSel 5, none */
- { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
- { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
- { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
- };
- common_fixup(0, 8, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for MIATA (EV56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 Fan Fault
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 none
- * 4 CID0 (Riser ID)
- * 5 CID1 (Riser ID)
- * 6 Interval timer
- * 7 PCI-ISA Bridge
- * 8 Ethernet
- * 9 EIDE (deprecated, ISA 14/15 used)
- *10 none
- *11 USB
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line A from slot 5
- *17 Interrupt line B from slot 5
- *18 Interrupt Line C from slot 5
- *19 Interrupt Line D from slot 5
- *20 Interrupt Line A from slot 1
- *21 Interrupt Line B from slot 1
- *22 Interrupt Line C from slot 1
- *23 Interrupt Line D from slot 1
- *24 Interrupt Line A from slot 2
- *25 Interrupt Line B from slot 2
- *26 Interrupt Line C from slot 2
- *27 Interrupt Line D from slot 2
- *27 Interrupt Line A from slot 3
- *29 Interrupt Line B from slot 3
- *30 Interrupt Line C from slot 3
- *31 Interrupt Line D from slot 3
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 3 DC21142 Ethernet
- * 4 EIDE CMD646
- * 5 none
- * 6 USB
- * 7 PCI-ISA bridge
- * 8 PCI-PCI Bridge (SBU Riser)
- * 9 none
- * 10 none
- * 11 PCI on board slot 4 (SBU Riser)
- * 12 PCI on board slot 5 (SBU Riser)
- *
- * These are behind the bridge, so I'm not sure what to do...
- *
- * 13 PCI on board slot 1 (SBU Riser)
- * 14 PCI on board slot 2 (SBU Riser)
- * 15 PCI on board slot 3 (SBU Riser)
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-
-#ifdef CONFIG_ALPHA_MIATA
-static inline void miata_fixup(void)
-{
- static char irq_tab[18][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
- { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
- { -1, -1, -1, -1, -1}, /* IdSel 16, none */
- { -1, -1, -1, -1, -1}, /* IdSel 17, none */
-/* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
- { -1, -1, -1, -1, -1}, /* IdSel 20, none */
- { -1, -1, -1, -1, -1}, /* IdSel 21, none */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
- /* The following are actually on bus 1, which is */
- /* across the builtin PCI-PCI bridge */
- {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */
- {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */
- {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */
- { -1, -1, -1, -1, -1}, /* IdSel 27, none */
- { -1, -1, -1, -1, -1}, /* IdSel 28, none */
- { -1, -1, -1, -1, -1}, /* IdSel 29, none */
- { -1, -1, -1, -1, -1}, /* IdSel 30, none */
- { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
- };
- common_fixup(3, 20, 5, irq_tab, 0);
- SMC669_Init(); /* it might be a GL (fails harmlessly if not) */
- es1888_init();
-}
-#endif
+ /*
+ * This device is not on the primary bus, we need
+ * to figure out which interrupt pin it will come
+ * in on. We know which slot it will come in on
+ * 'cos that slot is where the bridge is. Each
+ * time the interrupt line passes through a PCI-PCI
+ * bridge we must apply the swizzle function (see
+ * the inline static routine above).
+ */
+ dev->irq = 0;
-/*
- * Fixup configuration for SX164 (PCA56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 RSVD
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 MBZ
- * 4 RAZ
- * 5 RAZ
- * 6 Interval timer (RTC)
- * 7 PCI-ISA Bridge
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line A from slot 2
- *10 Interrupt Line A from slot 1
- *11 Interrupt Line A from slot 0
- *12 Interrupt Line B from slot 3
- *13 Interrupt Line B from slot 2
- *14 Interrupt Line B from slot 1
- *15 Interrupt line B from slot 0
- *16 Interrupt Line C from slot 3
- *17 Interrupt Line C from slot 2
- *18 Interrupt Line C from slot 1
- *19 Interrupt Line C from slot 0
- *20 Interrupt Line D from slot 3
- *21 Interrupt Line D from slot 2
- *22 Interrupt Line D from slot 1
- *23 Interrupt Line D from slot 0
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Cypress I/O
- * 9 32 bit PCI option slot 3
- *
- */
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ /* Cope with 0 and illegal. */
+ if (pin == 0 || pin > 4)
+ pin = 1;
-static inline void sx164_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
- { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
- { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
- { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
- { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
-
-/*
- * Fixup configuration for DP264 (EV6+TSUNAMI)
- *
- * Summary @ TSUNAMI_CSR_DIM0:
- * Bit Meaning
- * 0-17 Unused
- *18 Interrupt SCSI B (Adaptec 7895 builtin)
- *19 Interrupt SCSI A (Adaptec 7895 builtin)
- *20 Interrupt Line D from slot 2 PCI0
- *21 Interrupt Line C from slot 2 PCI0
- *22 Interrupt Line B from slot 2 PCI0
- *23 Interrupt Line A from slot 2 PCI0
- *24 Interrupt Line D from slot 1 PCI0
- *25 Interrupt Line C from slot 1 PCI0
- *26 Interrupt Line B from slot 1 PCI0
- *27 Interrupt Line A from slot 1 PCI0
- *28 Interrupt Line D from slot 0 PCI0
- *29 Interrupt Line C from slot 0 PCI0
- *30 Interrupt Line B from slot 0 PCI0
- *31 Interrupt Line A from slot 0 PCI0
- *
- *32 Interrupt Line D from slot 3 PCI1
- *33 Interrupt Line C from slot 3 PCI1
- *34 Interrupt Line B from slot 3 PCI1
- *35 Interrupt Line A from slot 3 PCI1
- *36 Interrupt Line D from slot 2 PCI1
- *37 Interrupt Line C from slot 2 PCI1
- *38 Interrupt Line B from slot 2 PCI1
- *39 Interrupt Line A from slot 2 PCI1
- *40 Interrupt Line D from slot 1 PCI1
- *41 Interrupt Line C from slot 1 PCI1
- *42 Interrupt Line B from slot 1 PCI1
- *43 Interrupt Line A from slot 1 PCI1
- *44 Interrupt Line D from slot 0 PCI1
- *45 Interrupt Line C from slot 0 PCI1
- *46 Interrupt Line B from slot 0 PCI1
- *47 Interrupt Line A from slot 0 PCI1
- *48-52 Unused
- *53 PCI0 NMI (from Cypress)
- *54 PCI0 SMI INT (from Cypress)
- *55 PCI0 ISA Interrupt (from Cypress)
- *56-60 Unused
- *61 PCI1 Bus Error
- *62 PCI0 Bus Error
- *63 Reserved
- *
- * IdSel
- * 5 Cypress Bridge I/O
- * 6 SCSI Adaptec builtin
- * 7 64 bit PCI option slot 0
- * 8 64 bit PCI option slot 1
- * 9 64 bit PCI option slot 2
- *
- */
+ if (!DEV_IS_ON_PRIMARY(dev)) {
+ /* Follow the chain of bridges, swizzling as we go. */
-static inline void dp264_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
- { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin */
- { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
- { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
- { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
+ int spill = pin;
+ slot = (*swizzle)(dev, &spill);
+ pin = spill;
-/*
- * Fixup configuration for RAWHIDE
- *
- * Summary @ MCPCIA_PCI0_INT_REQ:
- * Bit Meaning
- *0 Interrupt Line A from slot 2 PCI0
- *1 Interrupt Line B from slot 2 PCI0
- *2 Interrupt Line C from slot 2 PCI0
- *3 Interrupt Line D from slot 2 PCI0
- *4 Interrupt Line A from slot 3 PCI0
- *5 Interrupt Line B from slot 3 PCI0
- *6 Interrupt Line C from slot 3 PCI0
- *7 Interrupt Line D from slot 3 PCI0
- *8 Interrupt Line A from slot 4 PCI0
- *9 Interrupt Line B from slot 4 PCI0
- *10 Interrupt Line C from slot 4 PCI0
- *11 Interrupt Line D from slot 4 PCI0
- *12 Interrupt Line A from slot 5 PCI0
- *13 Interrupt Line B from slot 5 PCI0
- *14 Interrupt Line C from slot 5 PCI0
- *15 Interrupt Line D from slot 5 PCI0
- *16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
- *17-23 NA
- *
- * IdSel
- * 1 EISA bridge (PCI bus 0 only)
- * 2 PCI option slot 2
- * 3 PCI option slot 3
- * 4 PCI option slot 4
- * 5 PCI option slot 5
- *
- */
+ /* Must make sure that SRM didn't screw up
+ and allocate an address > 64K for I/O
+ space behind a PCI-PCI bridge. */
+ if (alpha_use_srm_setup)
+ check_behind_io(dev);
+ } else {
+ /* Just a device on a primary bus. */
+ slot = PCI_SLOT(dev->devfn);
+ }
-static inline void rawhide_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 only */
- { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
- { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
- { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
- { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
- };
- common_fixup(1, 5, 5, irq_tab, 0);
-}
+ irq = (*map_irq)(dev, slot, pin);
-/*
- * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
- * 19, and 18 respectively, in the default configuration. They can
- * also be jumpered to slots 8, 7, and 6 respectively, which is fun
- * because the SIO ISA bridge can also be slot 7. However, the SIO
- * doesn't explicitly generate PCI-type interrupts, so we can
- * assign it whatever the hell IRQ we like and it doesn't matter.
- */
-static inline void takara_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
- { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
- };
- common_fixup(6, 20, 5, irq_tab, 0x26e);
-}
-
-/*
- * Fixup configuration for all boards that route the PCI interrupts
- * through the SIO PCI/ISA bridge. This includes Noname (AXPpci33),
- * Avanti (AlphaStation) and Kenetics's Platform 2000.
- */
-static inline void sio_fixup(void)
-{
- struct pci_dev *dev;
- /*
- * The Noname board has 5 PCI slots with each of the 4
- * interrupt pins routed to different pins on the PCI/ISA
- * bridge (PIRQ0-PIRQ3). The table below is based on
- * information available at:
- *
- * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
- *
- * I have no information on the Avanti interrupt routing, but
- * the routing seems to be identical to the Noname except
- * that the Avanti has an additional slot whose routing I'm
- * unsure of.
- *
- * pirq_tab[0] is a fake entry to deal with old PCI boards
- * that have the interrupt pin number hardwired to 0 (meaning
- * that they use the default INTA line, if they are interrupt
- * driven at all).
- */
- static const char pirq_tab[][5] __initlocaldata = {
- /*INT A B C D */
-#ifdef CONFIG_ALPHA_P2K
- { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
- { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
- { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
-#else
- { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 2, 2, -1, -1, -1}, /* idsel 8 (Noname hack: slot closest to ISA) */
- {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
- { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
- { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
- { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
-#endif
- };
- const size_t pirq_tab_len = sizeof(pirq_tab)/sizeof(pirq_tab[0]);
+ DBG_DEVS(("common_pci_fixup: bus %d slot %d "
+ "pin %d irq %d\n",
+ dev->bus->number, slot, pin, irq));
- /*
- * route_tab selects irq routing in PCI/ISA bridge so that:
- * PIRQ0 -> irq 15
- * PIRQ1 -> irq 9
- * PIRQ2 -> irq 10
- * PIRQ3 -> irq 11
- *
- * This probably ought to be configurable via MILO. For
- * example, sound boards seem to like using IRQ 9.
- */
+ if (irq != -1)
+ dev->irq = irq;
-#if defined(CONFIG_ALPHA_BOOK1)
- /* for the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15 */
- const unsigned int new_route_tab = 0x0e0f0a0a;
+ if (alpha_using_srm) {
+ /* Read the original SRM-set IRQ and tell. */
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_LINE,
+ &irq_orig);
-#elif defined(CONFIG_ALPHA_NONAME)
- /*
- * For UDB, the only available PCI slot must not map to IRQ 9,
- * since that's the builtin MSS sound chip. That PCI slot
- * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
- * instead.
- *
- * Unfortunately we have to do this for NONAME as well, since
- * they are co-indicated when the platform type "Noname" is
- * selected... :-(
- */
- const unsigned int new_route_tab = 0x0b0a0f09;
-#else
- const unsigned int new_route_tab = 0x0b0a090f;
-#endif
- unsigned int route_tab, old_route_tab;
- unsigned int level_bits, old_level_bits;
- unsigned char pin, slot;
- int pirq;
-
- pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &old_route_tab);
- DBG_DEVS(("sio_fixup: old pirq route table: 0x%08x\n",
- old_route_tab));
-#if PCI_MODIFY
- route_tab = new_route_tab;
- pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
-#else
- route_tab = old_route_tab;
-#endif
+ if (irq_orig != dev->irq) {
+ struct reset_irq *r;
- /*
- * Go through all devices, fixing up irqs as we see fit:
- */
- level_bits = 0;
- for (dev = pci_devices; dev; dev = dev->next) {
- if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
- (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
- continue;
+ DBG_DEVS(("common_pci_fixup: bus %d "
+ "slot 0x%x SRM IRQ 0x%x "
+ "changed to 0x%x\n",
+ dev->bus->number,
+ PCI_SLOT(dev->devfn),
+ irq_orig, dev->irq));
- dev->irq = 0;
- if (dev->bus->number != 0) {
- struct pci_dev *curr = dev;
- /*
- * read the pin and do the PCI-PCI bridge
- * interrupt pin swizzle
- */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
- /* cope with 0 */
- if (pin == 0)
- pin = 1;
- /* follow the chain of bridges, swizzling as we go */
- do {
- /* swizzle */
- pin = bridge_swizzle(pin, PCI_SLOT(curr->devfn));
- /* move up the chain of bridges */
- curr = curr->bus->self;
- } while (curr->bus->self);
- /* The slot is the slot of the last bridge. */
- slot = PCI_SLOT(curr->devfn);
- } else {
- /* work out the slot */
- slot = PCI_SLOT(dev->devfn);
- /* read the pin */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
+ r = &srm_resets.irq[srm_resets.irq_count++];
+ r->dev = dev;
+ r->irq = irq_orig;
+ }
}
- if (slot < 6 || slot >= 6 + pirq_tab_len) {
- printk("bios32.sio_fixup: "
- "weird, found device %04x:%04x in"
- " non-existent slot %d!!\n",
- dev->vendor, dev->device, slot);
- continue;
- }
- pirq = pirq_tab[slot - 6][pin];
+ /* Always tell the device, so the driver knows what is
+ the real IRQ to use; the device does not use it. */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
+
+ DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x"
+ " VID 0x%x DID 0x%x\n"
+ " int_slot 0x%x pin 0x%x"
+ " pirq 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ dev->vendor, dev->device,
+ slot, pin, dev->irq));
- DBG_DEVS(("sio_fixup: bus %d slot 0x%x VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor,
- dev->device, slot, pin, pirq));
/*
- * if it's a VGA, enable its BIOS ROM at C0000
+ * If it's a VGA, enable its BIOS ROM at C0000.
*/
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
+ /* But if its a Cirrus 543x/544x DISABLE it,
+ since enabling ROM disables the memory... */
if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
(dev->device >= 0x00a0) &&
(dev->device <= 0x00ac)) {
} else {
pcibios_write_config_dword(
dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- continue; /* for now, displays get no IRQ */
- }
-
- if (pirq < 0) {
- DBG_DEVS(("bios32.sio_fixup: "
- "weird, device %04x:%04x coming in on"
- " slot %d has no irq line!!\n",
- dev->vendor, dev->device, slot));
- continue;
- }
-
- dev->irq = (route_tab >> (8 * pirq)) & 0xff;
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* do not set *ANY* level triggers for AlphaBook1 */
- /* must set the PCI IRQs to level triggered */
- level_bits |= (1 << dev->irq);
-#endif /* !CONFIG_ALPHA_BOOK1 */
-
-#if PCI_MODIFY
- /* tell the device: */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-#endif
-
-#ifdef CONFIG_ALPHA_BOOK1
- /*
- * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
- * is sensitive to PCI bus bursts, so we must DISABLE
- * burst mode for the NCR 8xx SCSI... :-(
- *
- * Note that the NCR810 SCSI driver must preserve the
- * setting of the bit in order for this to work. At the
- * moment (2.0.29), ncr53c8xx.c does NOT do this, but
- * 53c7,8xx.c DOES.
- */
- if (dev->vendor == PCI_VENDOR_ID_NCR &&
- (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
- dev->device == PCI_DEVICE_ID_NCR_53C815 ||
- dev->device == PCI_DEVICE_ID_NCR_53C820 ||
- dev->device == PCI_DEVICE_ID_NCR_53C825)) {
- unsigned int io_port;
- unsigned char ctest4;
-
- pcibios_read_config_dword(dev->bus->number,
- dev->devfn,
- PCI_BASE_ADDRESS_0,
- &io_port);
- io_port &= PCI_BASE_ADDRESS_IO_MASK;
- ctest4 = inb(io_port+0x21);
- if (!(ctest4 & 0x80)) {
- printk("AlphaBook1 NCR init: setting"
- " burst disable\n");
- outb(ctest4 | 0x80, io_port+0x21);
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
}
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
- } /* end for-devs */
-
- /*
- * Now, make all PCI interrupts level sensitive. Notice:
- * these registers must be accessed byte-wise. inw()/outw()
- * don't work.
- *
- * Make sure to turn off any level bits set for IRQs 9,10,11,15,
- * so that the only bits getting set are for devices actually found.
- * Note that we do preserve the remainder of the bits, which we hope
- * will be set correctly by ARC/SRM.
- *
- * Note: we at least preserve any level-set bits on AlphaBook1
- */
- old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
- DBG_DEVS(("sio_fixup: old irq level bits: 0x%04x\n",
- old_level_bits));
- level_bits |= (old_level_bits & 0x71ff);
- DBG_DEVS(("sio_fixup: new irq level bits: 0x%04x\n",
- level_bits));
- outb((level_bits >> 0) & 0xff, 0x4d0);
- outb((level_bits >> 8) & 0xff, 0x4d1);
-
-#ifdef CONFIG_ALPHA_BOOK1
- {
- unsigned char orig, config;
- /* On the AlphaBook1, make sure that register PR1
- indicates 1Mb mem */
- outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
- outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
- outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
- if ((config & 0xc0) != 0xc0) {
- printk("AlphaBook1 VGA init: setting 1Mb memory\n");
- config |= 0xc0;
- outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
- }
- outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* Do not do IDE init for AlphaBook1 */
- enable_ide(0x26e);
-#endif
-}
-
-
-__initfunc(void
-pcibios_fixup(void))
-{
- struct pci_bus *cur;
-
-#ifdef CONFIG_ALPHA_MCPCIA
- /* must do massive setup for multiple PCI busses here... */
- DBG_DEVS(("pcibios_fixup: calling mcpcia_fixup()...\n"));
- mcpcia_fixup();
-#endif /* MCPCIA */
-
-#ifdef CONFIG_ALPHA_TSUNAMI
- /* must do massive setup for multiple PCI busses here... */
- /* tsunami_fixup(); */
-#endif /* TSUNAMI */
-
-#if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN)
- /*
- * Scan the tree, allocating PCI memory and I/O space.
- */
- /*
- * Sigh; check_region() will need changing to accept a HANDLE,
- * if we allocate I/O space addresses on a per-bus basis.
- * For now, make the I/O bases unique across all busses, so
- * that check_region() will not get confused... ;-}
- */
- io_base = DEFAULT_IO_BASE;
- for (cur = &pci_root; cur; cur = cur->next) {
- mem_base = DEFAULT_MEM_BASE;
- DBG_DEVS(("pcibios_fixup: calling layout_bus()\n"));
- layout_bus(cur);
- }
-#endif
-
- /*
- * Now is the time to do all those dirty little deeds...
- */
-#if defined(CONFIG_ALPHA_NONAME) || defined(CONFIG_ALPHA_AVANTI) || \
- defined(CONFIG_ALPHA_P2K)
- sio_fixup();
-#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164)
- cabriolet_fixup();
-#elif defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
- alphapc164_fixup();
-#elif defined(CONFIG_ALPHA_EB66P)
- eb66p_fixup();
-#elif defined(CONFIG_ALPHA_EB66)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_EB64P)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_fixup();
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_fixup();
-#elif defined(CONFIG_ALPHA_SABLE)
- sable_fixup();
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_fixup();
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_fixup();
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_fixup();
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_fixup();
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_fixup();
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_fixup();
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- /* no fixup needed */
-#else
-# error "You must tell me what kind of platform you want."
-#endif
-}
-
-
-__initfunc(void
-pcibios_fixup_bus(struct pci_bus *bus))
-{
-}
-
-
-asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
- if (err != PCIBIOS_SUCCESSFUL)
- ubyte = 0xff;
- put_user(ubyte, buf);
- break;
- case 2:
- err = pcibios_read_config_word(bus, dfn, off, &ushort);
- if (err != PCIBIOS_SUCCESSFUL)
- ushort = 0xffff;
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- err = pcibios_read_config_dword(bus, dfn, off, &uint);
- if (err != PCIBIOS_SUCCESSFUL)
- uint = 0xffffffff;
- put_user(uint, (unsigned int *)buf);
- break;
- default:
- err = -EINVAL;
- break;
- }
- unlock_kernel();
- return err;
-}
-
-
-asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = get_user(ubyte, buf);
- if (err)
- break;
- err = pcibios_write_config_byte(bus, dfn, off, ubyte);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
}
- break;
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if (err)
- break;
- err = pcibios_write_config_word(bus, dfn, off, ushort);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if (err)
- break;
- err = pcibios_write_config_dword(bus, dfn, off, uint);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
+ /*
+ * If it's a SCSI, disable its BIOS ROM.
+ */
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
+ pcibios_write_config_dword(dev->bus->number,
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x0000000);
}
- break;
- default:
- err = -EINVAL;
- break;
}
- unlock_kernel();
- return err;
-}
-
-#if (defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164) || \
- defined(CONFIG_ALPHA_SX164) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_CABRIOLET)) && defined(CONFIG_ALPHA_SRM)
-
-/*
- on the above machines, under SRM console, we must use the CSERVE PALcode
- routine to manage the interrupt mask for us, otherwise, the kernel/HW get
- out of sync with what the PALcode thinks it needs to deliver/ignore
- */
-void
-cserve_update_hw(unsigned long irq, unsigned long mask)
-{
- extern void cserve_ena(unsigned long);
- extern void cserve_dis(unsigned long);
-
- if (mask & (1UL << irq))
- /* disable */
- cserve_dis(irq - 16);
- else
- /* enable */
- cserve_ena(irq - 16);
- return;
}
-#endif /* (PC164 || LX164 || SX164 || EB164 || CABRIO) && SRM */
-#ifdef CONFIG_ALPHA_MIATA
-/*
- * Init the built-in ES1888 sound chip (SB16 compatible)
- */
-static int __init
-es1888_init(void)
-{
- /* Sequence of IO reads to init the audio controller */
- inb(0x0229);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0220); /* This sets the base address to 0x220 */
-
- /* Sequence to set DMA channels */
- outb(0x01, 0x0226); /* reset */
- inb(0x0226); /* pause */
- outb(0x00, 0x0226); /* release reset */
- while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
- continue;
- inb(0x022a); /* pause */
- outb(0xc6, 0x022c); /* enable extended mode */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x14, 0x022c); /* set IRQ 5 */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb2, 0x022c); /* setup for write to DMA CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x18, 0x022c); /* set DMA channel 1 */
-
- return 0;
-}
-#endif /* CONFIG_ALPHA_MIATA */
+/* Most Alphas have straight-forward swizzling needs. */
-__initfunc(char *pcibios_setup(char *str))
+int __init
+common_swizzle(struct pci_dev *dev, int *pinp)
{
- return str;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-void reset_for_srm(void)
-{
- struct pci_dev *dev;
- int i;
+ int pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
- /* reset any IRQs that we changed */
- for (i = 0; i < irq_reset_count; i++) {
- dev = irq_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, irq_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed back from 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- irq_to_reset[i], dev->irq);
-#endif
- }
-
- /* reset any IO addresses that we changed */
- for (i = 0; i < io_reset_count; i++) {
- dev = io_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- io_reg_to_reset[i], io_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IO restored to 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- io_to_reset[i]);
-#endif
+ /* The slot is the slot of the last bridge. */
+ return PCI_SLOT(dev->devfn);
}
- /* FIXME: reset the video origin. */
-}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
-
#endif /* CONFIG_PCI */
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/bios32.h
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the PCI initialization routines in bios32.c.
+ */
+
+
+#define KB 1024
+#define MB (1024*KB)
+#define GB (1024*MB)
+
+/*
+ * We can't just blindly use 64K for machines with EISA busses; they
+ * may also have PCI-PCI bridges present, and then we'd configure the
+ * bridge incorrectly.
+ *
+ * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
+ * IO space areas allocated *before* 0xC000; this is because certain
+ * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
+ * accesses to probe the bus. If a device's registers appear at 0xC000,
+ * it may see an INx/OUTx at that address during BIOS emulation of the
+ * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
+ *
+ * Note that we may need this stuff for SRM_SETUP also, since certain
+ * SRM consoles screw up and allocate I/O space addresses > 64K behind
+ * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K,
+ * AFAIK.
+ */
+
+#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
+#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
+
+/*
+ * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
+ * that get passed through the PCI<->ISA bridge chip. Although this causes
+ * us to set the PCI->Mem window bases lower than normal, we still allocate
+ * PCI bus devices' memory addresses *below* the low DMA mapping window,
+ * and hope they fit below 64Mb (to avoid conflicts), and so that they can
+ * be accessed via SPARSE space.
+ *
+ * We accept the risk that a broken Myrinet card will be put into a true XL
+ * and thus can more easily run into the problem described below.
+ */
+#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
+
+/*
+ * We try to make this address *always* have more than 1 bit set.
+ * this is so that devices like the broken Myrinet card will always have
+ * a PCI memory address that will never match a IDSEL address in
+ * PCI Config space, which can cause problems with early rev cards.
+ *
+ * However, APECS and LCA have only 34 bits for physical addresses, thus
+ * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ */
+#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB)
+
+/*
+ * We try to make this address *always* have more than 1 bit set.
+ * this is so that devices like the broken Myrinet card will always have
+ * a PCI memory address that will never match a IDSEL address in
+ * PCI Config space, which can cause problems with early rev cards.
+ *
+ * Because CIA and PYXIS and T2 have more bits for physical addresses,
+ * they support an expanded range of SPARSE memory addresses.
+ */
+#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+
+
+/*
+ * PCI_MODIFY
+ *
+ * If this 0, then do not write to any of the PCI registers, merely
+ * read them (i.e., use configuration as determined by SRM). The SRM
+ * seem do be doing a less than perfect job in configuring PCI
+ * devices, so for now we do it ourselves. Reconfiguring PCI devices
+ * breaks console (RPB) callbacks, but those don't work properly with
+ * 64 bit addresses anyways.
+ *
+ * The accepted convention seems to be that the console (POST
+ * software) should fully configure boot devices and configure the
+ * interrupt routing of *all* devices. In particular, the base
+ * addresses of non-boot devices need not be initialized. For
+ * example, on the AXPpci33 board, the base address a #9 GXE PCI
+ * graphics card reads as zero (this may, however, be due to a bug in
+ * the graphics card---there have been some rumor that the #9 BIOS
+ * incorrectly resets that address to 0...).
+ */
+
+#define PCI_MODIFY (!alpha_use_srm_setup)
+
+
+/*
+ * A small note about bridges and interrupts. The DECchip 21050 (and
+ * later) adheres to the PCI-PCI bridge specification. This says that
+ * the interrupts on the other side of a bridge are swizzled in the
+ * following manner:
+ *
+ * Dev Interrupt Interrupt
+ * Pin on Pin on
+ * Device Connector
+ *
+ * 4 A A
+ * B B
+ * C C
+ * D D
+ *
+ * 5 A B
+ * B C
+ * C D
+ * D A
+ *
+ * 6 A C
+ * B D
+ * C A
+ * D B
+ *
+ * 7 A D
+ * B A
+ * C B
+ * D C
+ *
+ * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
+ * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
+ *
+ * The following code swizzles for exactly one bridge. The routine
+ * common_swizzle below handles multiple bridges. But there are a
+ * couple boards that do strange things, so we define this here.
+ */
+
+static inline unsigned char
+bridge_swizzle(unsigned char pin, unsigned int slot)
+{
+ return (((pin-1) + slot) % 4) + 1;
+}
+
+extern void layout_all_busses(unsigned long io_base, unsigned long mem_base);
+extern void enable_ide(long ide_base);
+
+struct pci_dev;
+
+extern void
+common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
+ int (*swizzle)(struct pci_dev *dev, int *pin));
+
+extern int common_swizzle(struct pci_dev *dev, int *pinp);
+
+/* The following macro is used to implement the table-based irq mapping
+ function for all single-bus Alphas. */
+
+#define COMMON_TABLE_LOOKUP \
+({ long _ctl_ = -1; \
+ if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot) \
+ _ctl_ = irq_tab[slot - min_idsel][pin]; \
+ _ctl_; })
+++ /dev/null
-/*
- * Code common to all CIA 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/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>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * Machine check reasons. Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_OS_BUGCHECK 0x008A
-#define MCHK_K_PAL_BUGCHECK 0x0090
-
-/*
- * BIOS32-style PCI interface:
- */
-
-/* #define DEBUG_MCHECK */
-/* #define DEBUG_CONFIG */
-/* #define DEBUG_DUMP_REGS */
-
-#ifdef DEBUG_MCHECK
-# define DBGM(args) printk args
-#else
-# define DBGM(args)
-#endif
-#ifdef DEBUG_CONFIG
-# define DBGC(args) printk args
-#else
-# define DBGC(args)
-#endif
-
-#define vuip volatile unsigned int *
-
-static volatile unsigned int CIA_mcheck_expected = 0;
-static volatile unsigned int CIA_mcheck_taken = 0;
-static unsigned int CIA_jd;
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
-unsigned int CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
-unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the CIA_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;
-
- DBGC(("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) {
- DBGC(("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;
- DBGC(("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 */
-
- value = 0xffffffffU;
- mb();
-
- save_flags(flags); /* avoid getting hit by machine check */
- cli();
-
- DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- *(vuip)CIA_IOC_CIA_ERR = stat0;
- mb();
- DBGC(("conf_read: CIA ERR was 0x%x\n", stat0));
- /* if Type1 access, must set CIA CFG */
- if (type1) {
- cia_cfg = *(vuip)CIA_IOC_CFG;
- *(vuip)CIA_IOC_CFG = cia_cfg | 1;
- mb();
- DBGC(("conf_read: TYPE1 access\n"));
- }
-
- mb();
- draina();
- CIA_mcheck_expected = 1;
- CIA_mcheck_taken = 0;
- mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
- if (CIA_mcheck_taken) {
- CIA_mcheck_taken = 0;
- value = 0xffffffffU;
- mb();
- }
- CIA_mcheck_expected = 0;
- mb();
-
-#if 0
- /*
- this code might be necessary if machine checks aren't taken,
- but I can't get it to work on CIA-2, so its disabled.
- */
- draina();
-
- /* now look for any errors */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0));
- if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */
- /* if not MAS_ABT, print status */
- if (!(stat0 & 0x0080)) {
- printk("CIA.c:conf_read: got stat0=%x\n", stat0);
- }
-
- /* reset error status: */
- *(vuip)CIA_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) {
- *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
- mb();
- }
-
- DBGC(("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 = *(vuip)CIA_IOC_CIA_ERR;
- *(vuip)CIA_IOC_CIA_ERR = stat0;
- mb();
- DBGC(("conf_write: CIA ERR was 0x%x\n", stat0));
- /* if Type1 access, must set CIA CFG */
- if (type1) {
- cia_cfg = *(vuip)CIA_IOC_CFG;
- *(vuip)CIA_IOC_CFG = cia_cfg | 1;
- mb();
- DBGC(("conf_write: TYPE1 access\n"));
- }
-
- draina();
- CIA_mcheck_expected = 1;
- mb();
- /* access configuration space: */
- *(vuip)addr = value;
- mb();
- mb(); /* magic */
-
- CIA_mcheck_expected = 0;
- mb();
-
-#if 0
- /*
- * This code might be necessary if machine checks aren't taken,
- * but I can't get it to work on CIA-2, so its disabled.
- */
- draina();
-
- /* Now look for any errors */
- stat0 = *(vuip)CIA_IOC_CIA_ERR;
- DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0));
- if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */
- /* If not MAS_ABT, print status */
- if (!(stat0 & 0x0080)) {
- printk("CIA.c:conf_read: got stat0=%x\n", stat0);
- }
-
- /* reset error status: */
- *(vuip)CIA_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) {
- *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
- mb();
- }
-
- DBGC(("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 = CIA_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 = CIA_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 = CIA_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 = CIA_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 = CIA_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 = CIA_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 cia_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned int cia_tmp;
-
-#ifdef DEBUG_DUMP_REGS
- {
- unsigned int temp;
- temp = *(vuip)CIA_IOC_CIA_REV; mb();
- printk("CIA_init: CIA_REV was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PCI_LAT; mb();
- printk("CIA_init: CIA_PCI_LAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("CIA_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)0xfffffc8740000140UL; mb();
- printk("CIA_init: CIA_CTRL1 was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_MEM; mb();
- printk("CIA_init: CIA_HAE_MEM was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_HAE_IO; mb();
- printk("CIA_init: CIA_HAE_IO was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("CIA_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CACK_EN; mb();
- printk("CIA_init: CIA_CACK_EN was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CFG; mb();
- printk("CIA_init: CIA_CFG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
- printk("CIA_init: CIA_DIAG was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
- printk("CIA_init: CIA_DIAG_CHECK was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
- printk("CIA_init: CIA_PERF_MONITOR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
- printk("CIA_init: CIA_PERF_CONTROL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_ERR; mb();
- printk("CIA_init: CIA_ERR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_STAT; mb();
- printk("CIA_init: CIA_STAT was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_MCR; mb();
- printk("CIA_init: CIA_MCR was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("CIA_init: CIA_CTRL was 0x%x\n", temp);
- temp = *(vuip)CIA_IOC_ERR_MASK; mb();
- printk("CIA_init: CIA_ERR_MASK was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
- printk("CIA_init: W0_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
- printk("CIA_init: W1_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
- printk("CIA_init: W2_BASE was 0x%x\n", temp);
- temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
- printk("CIA_init: W3_BASE was 0x%x\n", temp);
- }
-#endif /* DEBUG_DUMP_REGS */
-
- /*
- * Set up error reporting.
- */
- cia_tmp = *(vuip)CIA_IOC_CIA_ERR;
- cia_tmp |= 0x180; /* master, target abort */
- *(vuip)CIA_IOC_CIA_ERR = cia_tmp;
- mb();
-
- cia_tmp = *(vuip)CIA_IOC_CIA_CTRL;
- cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */
- *(vuip)CIA_IOC_CIA_CTRL = cia_tmp;
- mb();
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T0_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 0 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W0_BASE,
- *(vuip)CIA_IOC_PCI_W0_MASK,
- *(vuip)CIA_IOC_PCI_T0_BASE);
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T1_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 1 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W1_BASE,
- *(vuip)CIA_IOC_PCI_W1_MASK,
- *(vuip)CIA_IOC_PCI_T1_BASE);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T2_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 2 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W2_BASE,
- *(vuip)CIA_IOC_PCI_W2_MASK,
- *(vuip)CIA_IOC_PCI_T2_BASE);
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T3_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("cia_init: using Window 3 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W3_BASE,
- *(vuip)CIA_IOC_PCI_W3_MASK,
- *(vuip)CIA_IOC_PCI_T3_BASE);
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * 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)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)CIA_IOC_PCI_T0_BASE = 0;
-
- *(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("CIA_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- /*
- * Next, clear the CIA_CFG register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
- unsigned int cia_cfg = *((vuip)CIA_IOC_CFG); mb();
- if (cia_cfg) {
- printk("CIA_init: CFG was 0x%x\n", cia_cfg);
- *((vuip)CIA_IOC_CFG) = 0; mb();
- }
- }
-
- {
- unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
- unsigned int cia_hae_io = *((vuip)CIA_IOC_HAE_IO);
-#if 0
- printk("CIA_init: HAE_MEM was 0x%x\n", cia_hae_mem);
- printk("CIA_init: HAE_IO was 0x%x\n", cia_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- sigh... For the SRM setup, unless we know apriori what the HAE
- contents will be, we need to setup the arbitrary region bases
- so we can test against the range of addresses and tailor the
- region chosen for the SPARSE memory access.
-
- see include/asm-alpha/cia.h for the SPARSE mem read/write
- */
- cia_sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL; /* region 1 */
- cia_sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL; /* region 2 */
- cia_sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL; /* region 3 */
-
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in cia.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = cia_hae_mem;
-#else /* SRM_SETUP */
- *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
- cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
- *((vuip)CIA_IOC_HAE_IO) = 0; mb();
- cia_hae_io = *((vuip)CIA_IOC_HAE_IO);
-#endif /* SRM_SETUP */
- }
-
- return mem_start;
-}
-
-int cia_pci_clr_err(void)
-{
- CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
- DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
- *(vuip)CIA_IOC_CIA_ERR = 0x0180;
- mb();
- return 0;
-}
-
-void cia_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- struct el_common *mchk_header;
- struct el_procdata *mchk_procdata;
- struct el_CIA_sysdata_mcheck *mchk_sysdata;
- unsigned long * ptr;
- const char * reason;
- char buf[128];
- long i;
-
- mchk_header = (struct el_common *)la_ptr;
- mchk_procdata = (struct el_procdata *)
- (la_ptr + mchk_header->proc_offset);
- mchk_sysdata = (struct el_CIA_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
- DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBGM((" 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));
- DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- CIA_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-
-#ifdef DEBUG_MCHECK
- {
- 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
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (CIA_mcheck_expected) {
- DBGM(("CIA machine check expected\n"));
- CIA_mcheck_expected = 0;
- CIA_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- cia_pci_clr_err();
- wrmces(0x7);
- mb();
- return;
- }
-
- switch ((unsigned int) mchk_header->code) {
- case MCHK_K_TPERR: reason = "tag parity error"; break;
- case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "generic hard error"; break;
- case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
- case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
- case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
- case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
- case 0x96: reason = "i-cache read retryable error"; break;
- case 0x98: reason = "processor detected hard error"; break;
-
- /* system specific (these are for Alcor, at least): */
- case 0x203: reason = "system detected uncorrectable ECC error"; break;
- case 0x205: reason = "parity error detected by CIA"; break;
- case 0x207: reason = "non-existent memory error"; break;
- case 0x209: reason = "PCI SERR detected"; break;
- case 0x20b: reason = "PCI data parity error detected"; break;
- case 0x20d: reason = "PCI address parity error detected"; break;
- case 0x20f: reason = "PCI master abort error"; break;
- case 0x211: reason = "PCI target abort error"; break;
- case 0x213: reason = "scatter/gather PTE invalid error"; break;
- case 0x215: reason = "flash ROM write error"; break;
- case 0x217: reason = "IOA timeout detected"; break;
- case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
- case 0x21b: reason = "EISA fail-safe timer timeout"; break;
- case 0x21d: reason = "EISA bus time-out"; break;
- case 0x21f: reason = "EISA software generated NMI"; break;
- case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
- default:
- sprintf(buf, "reason for machine-check unknown (0x%x)",
- (unsigned int) mchk_header->code);
- reason = buf;
- break;
- }
- wrmces(rdmces()); /* reset machine check pending flag */
- mb();
-
- printk(KERN_CRIT " CIA machine check: %s%s\n",
- reason, mchk_header->retry ? " (retryable)" : "");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n",
- vector, la_ptr, regs->pc);
-
- /* dump the logout area to give all info: */
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_apecs.c
+ *
+ * Code common to all APECS core logic chips.
+ *
+ * Rewritten for Apecs from the lca.c from:
+ *
+ * Written by David Mosberger (davidm@cs.arizona.edu) with some code
+ * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
+ * bios code.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_apecs.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define vuip volatile unsigned int *
+
+volatile unsigned int apecs_mcheck_expected = 0;
+volatile unsigned int apecs_mcheck_taken = 0;
+static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the APECS_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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | | | | | | | | | | | | | | |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(u8 bus, u8 device_fn, u8 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 haxr2 = 0;
+
+ 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 = *(vuip)APECS_IOC_DCSR;
+ *(vuip)APECS_IOC_DCSR = stat0;
+ mb();
+ DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set HAE #2. */
+ if (type1) {
+ haxr2 = *(vuip)APECS_IOC_HAXR2;
+ mb();
+ *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ draina();
+ apecs_mcheck_expected = 1;
+ apecs_mcheck_taken = 0;
+ mb();
+
+ /* Access configuration space. */
+
+ /* Some SRMs step on these registers during a machine check. */
+ asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
+ : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
+
+ if (apecs_mcheck_taken) {
+ apecs_mcheck_taken = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ apecs_mcheck_expected = 0;
+ mb();
+
+#if 1
+ /*
+ * 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.
+ */
+ draina();
+
+ /* Now look for any errors. */
+ stat0 = *(vuip)APECS_IOC_DCSR;
+ DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
+
+ /* Is any error bit set? */
+ if (stat0 & 0xffe0U) {
+ /* If not NDEV, print status. */
+ if (!(stat0 & 0x0800)) {
+ printk("apecs.c:conf_read: got stat0=%x\n", stat0);
+ }
+
+ /* Reset error status. */
+ *(vuip)APECS_IOC_DCSR = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+ value = 0xffffffff;
+ }
+#endif
+
+ /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
+ if (type1) {
+ *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
+ mb();
+ }
+ 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 haxr2 = 0;
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)APECS_IOC_DCSR;
+ *(vuip)APECS_IOC_DCSR = stat0;
+ mb();
+
+ /* If Type1 access, must set HAE #2. */
+ if (type1) {
+ haxr2 = *(vuip)APECS_IOC_HAXR2;
+ mb();
+ *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
+ }
+
+ draina();
+ apecs_mcheck_expected = 1;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ mb();
+ mb(); /* magic */
+ apecs_mcheck_expected = 0;
+ mb();
+
+#if 1
+ /*
+ * 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.
+ */
+ draina();
+
+ /* Now look for any errors. */
+ stat0 = *(vuip)APECS_IOC_DCSR;
+
+ /* Is any error bit set? */
+ if (stat0 & 0xffe0U) {
+ /* If not NDEV, print status. */
+ if (!(stat0 & 0x0800)) {
+ printk("apecs.c:conf_write: got stat0=%x\n", stat0);
+ }
+
+ /* Reset error status. */
+ *(vuip)APECS_IOC_DCSR = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+ }
+#endif
+
+ /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
+ if (type1) {
+ *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
+ mb();
+ }
+ restore_flags(flags);
+}
+
+int
+apecs_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = APECS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apecs_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = APECS_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apecs_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = APECS_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apecs_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = APECS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apecs_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = APECS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+apecs_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = APECS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 1 for enabled and mapped to 0. */
+ if ((*(vuip)APECS_IOC_PB1R & (1U<<19))
+ && (*(vuip)APECS_IOC_TB1R == 0)) {
+ APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("apecs_init: using Window 1 settings\n");
+ printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
+ *(vuip)APECS_IOC_PB1R,
+ *(vuip)APECS_IOC_PM1R,
+ *(vuip)APECS_IOC_TB1R);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if ((*(vuip)APECS_IOC_PB2R & (1U<<19))
+ && (*(vuip)APECS_IOC_TB2R == 0)) {
+ APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("apecs_init: using Window 2 settings\n");
+ printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
+ *(vuip)APECS_IOC_PB2R,
+ *(vuip)APECS_IOC_PM2R,
+ *(vuip)APECS_IOC_TB2R);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
+ APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA. Window 1
+ * goes at 1 GB and is 1 GB large.
+ */
+ *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
+
+ *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+ break;
+ }
+
+ /*
+ * Finally, clear the HAXR2 register, which gets used
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
+ */
+ *(vuip)APECS_IOC_HAXR2 = 0; mb();
+}
+
+int
+apecs_pci_clr_err(void)
+{
+ apecs_jd = *(vuip)APECS_IOC_DCSR;
+ if (apecs_jd & 0xffe0L) {
+ apecs_jd1 = *(vuip)APECS_IOC_SEAR;
+ *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L;
+ apecs_jd = *(vuip)APECS_IOC_DCSR;
+ mb();
+ }
+ *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
+ apecs_jd2 = *(vuip)APECS_IOC_TBIA;
+ mb();
+ return 0;
+}
+
+void
+apecs_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_common *mchk_header;
+ struct el_apecs_procdata *mchk_procdata;
+ struct el_apecs_sysdata_mcheck *mchk_sysdata;
+ unsigned long *ptr;
+ int i;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_procdata = (struct el_apecs_procdata *)
+ (la_ptr + mchk_header->proc_offset
+ - sizeof(mchk_procdata->paltemp));
+
+ mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#ifdef DEBUG
+ printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(" 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);
+ printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+ 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
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+
+ if (apecs_mcheck_expected
+ && (mchk_sysdata->epic_dcsr & 0x0c00UL)) {
+ apecs_mcheck_expected = 0;
+ apecs_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ apecs_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ draina();
+ DBG(("apecs_machine_check: EXPECTED\n"));
+ }
+ else if (vector == 0x620 || vector == 0x630) {
+ /* Disable correctable from now on. */
+ wrmces(0x1f);
+ mb();
+ draina();
+ printk("apecs_machine_check: HW correctable (0x%lx)\n",
+ vector);
+ }
+ else {
+ printk(KERN_CRIT "APECS machine check:\n");
+ printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(KERN_CRIT
+ " 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);
+ printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%lx %lx %lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+#if 0
+ /* doesn't work with MILO */
+ show_regs(regs);
+#endif
+ }
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_cia.c
+ *
+ * Code common to all CIA core logic 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/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/ptrace.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_cia.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+extern asmlinkage void wrmces(unsigned long mces);
+
+/*
+ * Machine check reasons. Defined according to PALcode sources
+ * (osf.h and platform.h).
+ */
+#define MCHK_K_TPERR 0x0080
+#define MCHK_K_TCPERR 0x0082
+#define MCHK_K_HERR 0x0084
+#define MCHK_K_ECC_C 0x0086
+#define MCHK_K_ECC_NC 0x0088
+#define MCHK_K_OS_BUGCHECK 0x008A
+#define MCHK_K_PAL_BUGCHECK 0x0090
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#define DEBUG_MCHECK 0
+#define DEBUG_CONFIG 0
+/* #define DEBUG_DUMP_REGS */
+
+#if DEBUG_MCHECK
+# define DBGM(args) printk args
+#else
+# define DBGM(args)
+#endif
+#if DEBUG_CONFIG
+# define DBGC(args) printk args
+#else
+# define DBGC(args)
+#endif
+
+#define vuip volatile unsigned int *
+
+static volatile unsigned int CIA_mcheck_expected = 0;
+static volatile unsigned int CIA_mcheck_taken = 0;
+static unsigned int CIA_jd;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the CIA_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(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+
+ DBGC(("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) {
+ DBGC(("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;
+ DBGC(("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;
+
+ value = 0xffffffffU;
+ mb();
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)CIA_IOC_CIA_ERR;
+ *(vuip)CIA_IOC_CIA_ERR = stat0;
+ mb();
+ DBGC(("conf_read: CIA ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set CIA CFG. */
+ if (type1) {
+ cia_cfg = *(vuip)CIA_IOC_CFG;
+ *(vuip)CIA_IOC_CFG = cia_cfg | 1;
+ mb();
+ DBGC(("conf_read: TYPE1 access\n"));
+ }
+
+ mb();
+ draina();
+ CIA_mcheck_expected = 1;
+ CIA_mcheck_taken = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *(vuip)addr;
+ mb();
+ mb(); /* magic */
+ if (CIA_mcheck_taken) {
+ CIA_mcheck_taken = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ CIA_mcheck_expected = 0;
+ mb();
+
+#if 0
+ /* This code might be necessary if machine checks aren't taken,
+ but I can't get it to work on CIA-2, so its disabled. */
+ draina();
+
+ /* Now look for any errors. */
+ stat0 = *(vuip)CIA_IOC_CIA_ERR;
+ DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0));
+
+ /* Is any error bit set? */
+ if (stat0 & 0x8FEF0FFFU) {
+ /* If not MAS_ABT, print status. */
+ if (!(stat0 & 0x0080)) {
+ printk("CIA.c:conf_read: got stat0=%x\n", stat0);
+ }
+
+ /* reset error status: */
+ *(vuip)CIA_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) {
+ *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
+ mb();
+ }
+
+ DBGC(("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;
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)CIA_IOC_CIA_ERR;
+ *(vuip)CIA_IOC_CIA_ERR = stat0;
+ mb();
+ DBGC(("conf_write: CIA ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set CIA CFG. */
+ if (type1) {
+ cia_cfg = *(vuip)CIA_IOC_CFG;
+ *(vuip)CIA_IOC_CFG = cia_cfg | 1;
+ mb();
+ DBGC(("conf_write: TYPE1 access\n"));
+ }
+
+ draina();
+ CIA_mcheck_expected = 1;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ mb();
+ mb(); /* magic */
+
+ CIA_mcheck_expected = 0;
+ mb();
+
+#if 0
+ /* This code might be necessary if machine checks aren't taken,
+ but I can't get it to work on CIA-2, so its disabled. */
+ draina();
+
+ /* Now look for any errors */
+ stat0 = *(vuip)CIA_IOC_CIA_ERR;
+ DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0));
+
+ /* Is any error bit set? */
+ if (stat0 & 0x8FEF0FFFU) {
+ /* If not MAS_ABT, print status */
+ if (!(stat0 & 0x0080)) {
+ printk("CIA.c:conf_read: got stat0=%x\n", stat0);
+ }
+
+ /* Reset error status. */
+ *(vuip)CIA_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) {
+ *(vuip)CIA_IOC_CFG = cia_cfg & ~1;
+ mb();
+ }
+
+ DBGC(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+int
+cia_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = CIA_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+cia_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = CIA_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+cia_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = CIA_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+cia_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = CIA_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+cia_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = CIA_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+cia_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = CIA_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ unsigned int cia_tmp;
+
+#ifdef DEBUG_DUMP_REGS
+ {
+ unsigned int temp;
+ temp = *(vuip)CIA_IOC_CIA_REV; mb();
+ printk("cia_init: CIA_REV was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PCI_LAT; mb();
+ printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+ temp = *(vuip)0xfffffc8740000140UL; mb();
+ printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_HAE_MEM; mb();
+ printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_HAE_IO; mb();
+ printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CFG; mb();
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CACK_EN; mb();
+ printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CFG; mb();
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
+ printk("cia_init: CIA_DIAG was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
+ printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
+ printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
+ printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_ERR; mb();
+ printk("cia_init: CIA_ERR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_STAT; mb();
+ printk("cia_init: CIA_STAT was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_MCR; mb();
+ printk("cia_init: CIA_MCR was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+ temp = *(vuip)CIA_IOC_ERR_MASK; mb();
+ printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
+ printk("cia_init: W0_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
+ printk("cia_init: W1_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
+ printk("cia_init: W2_BASE was 0x%x\n", temp);
+ temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
+ printk("cia_init: W3_BASE was 0x%x\n", temp);
+ }
+#endif /* DEBUG_DUMP_REGS */
+
+ /*
+ * Set up error reporting.
+ */
+ cia_tmp = *(vuip)CIA_IOC_CIA_ERR;
+ cia_tmp |= 0x180; /* master, target abort */
+ *(vuip)CIA_IOC_CIA_ERR = cia_tmp;
+ mb();
+
+ cia_tmp = *(vuip)CIA_IOC_CIA_CTRL;
+ cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */
+ *(vuip)CIA_IOC_CIA_CTRL = cia_tmp;
+ mb();
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0 */
+ if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("cia_init: using Window 0 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W0_BASE,
+ *(vuip)CIA_IOC_PCI_W0_MASK,
+ *(vuip)CIA_IOC_PCI_T0_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("cia_init: using Window 1 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W1_BASE,
+ *(vuip)CIA_IOC_PCI_W1_MASK,
+ *(vuip)CIA_IOC_PCI_T1_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("cia_init: using Window 2 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W2_BASE,
+ *(vuip)CIA_IOC_PCI_W2_MASK,
+ *(vuip)CIA_IOC_PCI_T2_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("cia_init: using Window 3 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W3_BASE,
+ *(vuip)CIA_IOC_PCI_W3_MASK,
+ *(vuip)CIA_IOC_PCI_T3_BASE);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
+ CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * 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)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)CIA_IOC_PCI_T0_BASE = 0;
+
+ *(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
+ *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
+ *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
+ break;
+ }
+
+ /*
+ * Next, clear the CIA_CFG register, which gets used
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
+ */
+ *((vuip)CIA_IOC_CFG) = 0; mb();
+
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/cia.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
+
+ alpha_mv.sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in cia.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = cia_hae_mem;
+
+ alpha_mv.mv_readb = cia_srm_readb;
+ alpha_mv.mv_readw = cia_srm_readw;
+ alpha_mv.mv_writeb = cia_srm_writeb;
+ alpha_mv.mv_writew = cia_srm_writew;
+ } else {
+ *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
+ *((vuip)CIA_IOC_HAE_MEM); /* read it back. */
+ *((vuip)CIA_IOC_HAE_IO) = 0; mb();
+ *((vuip)CIA_IOC_HAE_IO); /* read it back. */
+ }
+}
+
+static int
+cia_pci_clr_err(void)
+{
+ CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
+ DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
+ *(vuip)CIA_IOC_CIA_ERR = 0x0180;
+ mb();
+ return 0;
+}
+
+void
+cia_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_common *mchk_header;
+ struct el_CIA_procdata *mchk_procdata;
+ struct el_CIA_sysdata_mcheck *mchk_sysdata;
+ unsigned long * ptr;
+ const char * reason;
+ char buf[128];
+ long i;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_procdata = (struct el_CIA_procdata *)
+ (la_ptr + mchk_header->proc_offset);
+
+ mchk_sysdata = (struct el_CIA_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+ DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBGM((" 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));
+ DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ CIA_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear));
+
+#if DEBUG_MCHECK
+ {
+ 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
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (CIA_mcheck_expected) {
+ DBGM(("CIA machine check expected\n"));
+ CIA_mcheck_expected = 0;
+ CIA_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ cia_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ return;
+ }
+
+ switch ((unsigned int) mchk_header->code) {
+ case MCHK_K_TPERR: reason = "tag parity error"; break;
+ case MCHK_K_TCPERR: reason = "tag control parity error"; break;
+ case MCHK_K_HERR: reason = "generic hard error"; break;
+ case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
+ case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
+ case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
+ case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
+ case 0x96: reason = "i-cache read retryable error"; break;
+ case 0x98: reason = "processor detected hard error"; break;
+
+ /* System specific (these are for Alcor, at least): */
+ case 0x203: reason = "system detected uncorrectable ECC error"; break;
+ case 0x205: reason = "parity error detected by CIA"; break;
+ case 0x207: reason = "non-existent memory error"; break;
+ case 0x209: reason = "PCI SERR detected"; break;
+ case 0x20b: reason = "PCI data parity error detected"; break;
+ case 0x20d: reason = "PCI address parity error detected"; break;
+ case 0x20f: reason = "PCI master abort error"; break;
+ case 0x211: reason = "PCI target abort error"; break;
+ case 0x213: reason = "scatter/gather PTE invalid error"; break;
+ case 0x215: reason = "flash ROM write error"; break;
+ case 0x217: reason = "IOA timeout detected"; break;
+ case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
+ case 0x21b: reason = "EISA fail-safe timer timeout"; break;
+ case 0x21d: reason = "EISA bus time-out"; break;
+ case 0x21f: reason = "EISA software generated NMI"; break;
+ case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
+ default:
+ sprintf(buf, "reason for machine-check unknown (0x%x)",
+ (unsigned int) mchk_header->code);
+ reason = buf;
+ break;
+ }
+ wrmces(rdmces()); /* reset machine check pending flag */
+ mb();
+
+ printk(KERN_CRIT "CIA machine check: %s%s\n",
+ reason, mchk_header->retry ? " (retryable)" : "");
+ printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n",
+ vector, la_ptr, regs->pc);
+
+ /* Dump the logout area to give all info. */
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_lca.c
+ *
+ * Code common to all LCA core logic chips.
+ *
+ * Written by David Mosberger (davidm@cs.arizona.edu) with some code
+ * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
+ * bios code.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_lca.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+/*
+ * Machine check reasons. Defined according to PALcode sources
+ * (osf.h and platform.h).
+ */
+#define MCHK_K_TPERR 0x0080
+#define MCHK_K_TCPERR 0x0082
+#define MCHK_K_HERR 0x0084
+#define MCHK_K_ECC_C 0x0086
+#define MCHK_K_ECC_NC 0x0088
+#define MCHK_K_UNKNOWN 0x008A
+#define MCHK_K_CACKSOFT 0x008C
+#define MCHK_K_BUGCHECK 0x008E
+#define MCHK_K_OS_BUGCHECK 0x0090
+#define MCHK_K_DCPERR 0x0092
+#define MCHK_K_ICPERR 0x0094
+
+
+/*
+ * Platform-specific machine-check reasons:
+ */
+#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */
+#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
+#define MCHK_K_DCSR 0x208 /* all but Noname */
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the LCA_IOC_CONF 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | | | | | | | | | | | | | | |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(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr)
+{
+ unsigned long addr;
+
+ if (bus == 0) {
+ int device = device_fn >> 3;
+ int func = device_fn & 0x7;
+
+ /* Type 0 configuration cycle. */
+
+ if (device > 12) {
+ return -1;
+ }
+
+ *(vulp)LCA_IOC_CONF = 0;
+ addr = (1 << (11 + device)) | (func << 8) | where;
+ } else {
+ /* Type 1 configuration cycle. */
+ *(vulp)LCA_IOC_CONF = 1;
+ addr = (bus << 16) | (device_fn << 8) | where;
+ }
+ *pci_addr = addr;
+ return 0;
+}
+
+static unsigned int
+conf_read(unsigned long addr)
+{
+ unsigned long flags, code, stat0;
+ unsigned int value;
+
+ save_flags(flags);
+ cli();
+
+ /* Reset status register to avoid loosing errors. */
+ stat0 = *(vulp)LCA_IOC_STAT0;
+ *(vulp)LCA_IOC_STAT0 = stat0;
+ mb();
+
+ /* Access configuration space. */
+ value = *(vuip)addr;
+ draina();
+
+ stat0 = *(vulp)LCA_IOC_STAT0;
+ if (stat0 & LCA_IOC_STAT0_ERR) {
+ code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
+ & LCA_IOC_STAT0_CODE_MASK);
+ if (code != 1) {
+ printk("lca.c:conf_read: got stat0=%lx\n", stat0);
+ }
+
+ /* Reset error status. */
+ *(vulp)LCA_IOC_STAT0 = stat0;
+ mb();
+
+ /* Reset machine check. */
+ wrmces(0x7);
+
+ value = 0xffffffff;
+ }
+ restore_flags(flags);
+ return value;
+}
+
+static void
+conf_write(unsigned long addr, unsigned int value)
+{
+ unsigned long flags, code, stat0;
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ /* Reset status register to avoid loosing errors. */
+ stat0 = *(vulp)LCA_IOC_STAT0;
+ *(vulp)LCA_IOC_STAT0 = stat0;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ draina();
+
+ stat0 = *(vulp)LCA_IOC_STAT0;
+ if (stat0 & LCA_IOC_STAT0_ERR) {
+ code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
+ & LCA_IOC_STAT0_CODE_MASK);
+ if (code != 1) {
+ printk("lca.c:conf_write: got stat0=%lx\n", stat0);
+ }
+
+ /* Reset error status. */
+ *(vulp)LCA_IOC_STAT0 = stat0;
+ mb();
+
+ /* Reset machine check. */
+ wrmces(0x7);
+ }
+ restore_flags(flags);
+}
+
+int
+lca_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ *value = conf_read(addr) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+lca_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xffff;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ *value = conf_read(addr) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+lca_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xffffffff;
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+lca_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+lca_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+lca_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33))
+ && (*(vulp)LCA_IOC_T_BASE0 == 0)) {
+ LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE += 1;
+#if 0
+ printk("lca_init: using Window 0 settings\n");
+ printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)LCA_IOC_W_BASE0,
+ *(vulp)LCA_IOC_W_MASK0,
+ *(vulp)LCA_IOC_T_BASE0);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33))
+ && (*(vulp)LCA_IOC_T_BASE1 == 0)) {
+ LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE += 1;
+#if 1
+ printk("lca_init: using Window 1 settings\n");
+ printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)LCA_IOC_W_BASE1,
+ *(vulp)LCA_IOC_W_MASK1,
+ *(vulp)LCA_IOC_T_BASE1);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
+ LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 1 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+ *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
+
+ *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT;
+ *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1;
+ *(vulp)LCA_IOC_T_BASE0 = 0;
+ break;
+ }
+
+ /*
+ * Disable PCI parity for now. The NCR53c810 chip has
+ * troubles meeting the PCI spec which results in
+ * data parity errors.
+ */
+ *(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
+}
+
+/*
+ * Constants used during machine-check handling. I suppose these
+ * could be moved into lca.h but I don't see much reason why anybody
+ * else would want to use them.
+ */
+
+#define ESR_EAV (1UL<< 0) /* error address valid */
+#define ESR_CEE (1UL<< 1) /* correctable error */
+#define ESR_UEE (1UL<< 2) /* uncorrectable error */
+#define ESR_WRE (1UL<< 3) /* write-error */
+#define ESR_SOR (1UL<< 4) /* error source */
+#define ESR_CTE (1UL<< 7) /* cache-tag error */
+#define ESR_MSE (1UL<< 9) /* multiple soft errors */
+#define ESR_MHE (1UL<<10) /* multiple hard errors */
+#define ESR_NXM (1UL<<12) /* non-existent memory */
+
+#define IOC_ERR ( 1<<4) /* ioc logs an error */
+#define IOC_CMD_SHIFT 0
+#define IOC_CMD (0xf<<IOC_CMD_SHIFT)
+#define IOC_CODE_SHIFT 8
+#define IOC_CODE (0xf<<IOC_CODE_SHIFT)
+#define IOC_LOST ( 1<<5)
+#define IOC_P_NBR ((__u32) ~((1<<13) - 1))
+
+static void
+mem_error (unsigned long esr, unsigned long ear)
+{
+ printk(" %s %s error to %s occurred at address %x\n",
+ ((esr & ESR_CEE) ? "Correctable" :
+ (esr & ESR_UEE) ? "Uncorrectable" : "A"),
+ (esr & ESR_WRE) ? "write" : "read",
+ (esr & ESR_SOR) ? "memory" : "b-cache",
+ (unsigned) (ear & 0x1ffffff8));
+ if (esr & ESR_CTE) {
+ printk(" A b-cache tag parity error was detected.\n");
+ }
+ if (esr & ESR_MSE) {
+ printk(" Several other correctable errors occurred.\n");
+ }
+ if (esr & ESR_MHE) {
+ printk(" Several other uncorrectable errors occurred.\n");
+ }
+ if (esr & ESR_NXM) {
+ printk(" Attempted to access non-existent memory.\n");
+ }
+}
+
+static void
+ioc_error (__u32 stat0, __u32 stat1)
+{
+ static const char * const pci_cmd[] = {
+ "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
+ "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3",
+ "Rsvd4", "Configuration Read", "Configuration Write",
+ "Memory Read Multiple", "Dual Address", "Memory Read Line",
+ "Memory Write and Invalidate"
+ };
+ static const char * const err_name[] = {
+ "exceeded retry limit", "no device", "bad data parity",
+ "target abort", "bad address parity", "page table read error",
+ "invalid page", "data error"
+ };
+ unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
+ unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT;
+
+ printk(" %s initiated PCI %s cycle to address %x"
+ " failed due to %s.\n",
+ code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
+
+ if (code == 5 || code == 6) {
+ printk(" (Error occurred at PCI memory address %x.)\n",
+ (stat0 & ~IOC_P_NBR));
+ }
+ if (stat0 & IOC_LOST) {
+ printk(" Other PCI errors occurred simultaneously.\n");
+ }
+}
+
+void
+lca_machine_check (unsigned long vector, unsigned long la,
+ struct pt_regs *regs)
+{
+ unsigned long * ptr;
+ const char * reason;
+ union el_lca el;
+ char buf[128];
+ long i;
+
+ printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
+ la, regs->pc);
+ el.c = (struct el_common *) la;
+
+ /*
+ * The first quadword after the common header always seems to
+ * be the machine check reason---don't know why this isn't
+ * part of the common header instead. In the case of a long
+ * logout frame, the upper 32 bits is the machine check
+ * revision level, which we ignore for now.
+ */
+ switch (el.c->code & 0xffffffff) {
+ case MCHK_K_TPERR: reason = "tag parity error"; break;
+ case MCHK_K_TCPERR: reason = "tag control parity error"; break;
+ case MCHK_K_HERR: reason = "access to non-existent memory"; break;
+ case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
+ case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
+ case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
+ case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
+ case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
+ case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
+ case MCHK_K_ICPERR: reason = "i-cache parity error"; break;
+ case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break;
+ case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
+ case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
+ case MCHK_K_UNKNOWN:
+ default:
+ sprintf(buf, "reason for machine-check unknown (0x%lx)",
+ el.c->code & 0xffffffff);
+ reason = buf;
+ break;
+ }
+
+ wrmces(rdmces()); /* reset machine check pending flag */
+
+ switch (el.c->size) {
+ case sizeof(struct el_lca_mcheck_short):
+ printk(KERN_CRIT
+ " Reason: %s (short frame%s, dc_stat=%lx):\n",
+ reason, el.c->retry ? ", retryable" : "",
+ el.s->dc_stat);
+ if (el.s->esr & ESR_EAV) {
+ mem_error(el.s->esr, el.s->ear);
+ }
+ if (el.s->ioc_stat0 & IOC_ERR) {
+ ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
+ }
+ break;
+
+ case sizeof(struct el_lca_mcheck_long):
+ printk(KERN_CRIT " Reason: %s (long frame%s):\n",
+ reason, el.c->retry ? ", retryable" : "");
+ printk(KERN_CRIT
+ " reason: %lx exc_addr: %lx dc_stat: %lx\n",
+ el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
+ printk(KERN_CRIT " car: %lx\n", el.l->car);
+ if (el.l->esr & ESR_EAV) {
+ mem_error(el.l->esr, el.l->ear);
+ }
+ if (el.l->ioc_stat0 & IOC_ERR) {
+ ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
+ }
+ break;
+
+ default:
+ printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size);
+ }
+
+ /* Dump the logout area to give all info. */
+
+ ptr = (unsigned long *) la;
+ for (i = 0; i < el.c->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+}
+
+/*
+ * The following routines are needed to support the SPEED changing
+ * necessary to successfully manage the thermal problem on the AlphaBook1.
+ */
+
+void
+lca_clock_print(void)
+{
+ long pmr_reg;
+
+ pmr_reg = LCA_READ_PMR;
+
+ printk("Status of clock control:\n");
+ printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg));
+ printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg));
+ printk("\tInterrupt override is %s\n",
+ (pmr_reg & LCA_PMR_INTO) ? "on" : "off");
+ printk("\tDMA override is %s\n",
+ (pmr_reg & LCA_PMR_DMAO) ? "on" : "off");
+
+}
+
+int
+lca_get_clock(void)
+{
+ long pmr_reg;
+
+ pmr_reg = LCA_READ_PMR;
+ return(LCA_GET_PRIMARY(pmr_reg));
+
+}
+
+void
+lca_clock_fiddle(int divisor)
+{
+ long pmr_reg;
+
+ pmr_reg = LCA_READ_PMR;
+ LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor);
+ /* lca_norm_clock = divisor; */
+ LCA_WRITE_PMR(pmr_reg);
+ mb();
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_mcpcia.c
+ *
+ * Code common to all MCbus-PCI Adaptor core logic chipsets
+ *
+ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/pci.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_mcpcia.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+extern asmlinkage void wrmces(unsigned long mces);
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#undef DEBUG_CFG
+
+#ifdef DEBUG_CFG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+#undef DEBUG_PCI
+
+#ifdef DEBUG_PCI
+# define DBG_PCI(args) printk args
+#else
+# define DBG_PCI(args)
+#endif
+
+#define DEBUG_MCHECK
+
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+# define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
+static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
+static unsigned int MCPCIA_jd[NR_CPUS];
+
+#define MCPCIA_MAX_HOSES 2
+static int mcpcia_num_hoses = 0;
+
+static int pci_probe_enabled = 0; /* disable to start */
+
+static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose;
+
+static inline unsigned long long_align(unsigned long addr)
+{
+ return ((addr + (sizeof(unsigned long) - 1)) &
+ ~(sizeof(unsigned long) - 1));
+}
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the MCPCIA_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 unsigned int
+conf_read(unsigned long addr, unsigned char type1,
+ struct linux_hose_info *hose)
+{
+ unsigned long flags;
+ unsigned long hoseno = hose->pci_hose_index;
+ unsigned int stat0, value, temp, cpu;
+
+ cpu = smp_processor_id();
+
+ save_and_cli(flags);
+
+ DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
+ addr, type1, hoseno));
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+
+ mb();
+ draina();
+ MCPCIA_mcheck_expected[cpu] = 1;
+ MCPCIA_mcheck_taken[cpu] = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *((vuip)addr);
+ mb();
+ mb(); /* magic */
+
+ if (MCPCIA_mcheck_taken[cpu]) {
+ MCPCIA_mcheck_taken[cpu] = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ MCPCIA_mcheck_expected[cpu] = 0;
+ mb();
+
+ DBG_CFG(("conf_read(): finished\n"));
+
+ restore_flags(flags);
+ return value;
+}
+
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1,
+ struct linux_hose_info *hose)
+{
+ unsigned long flags;
+ unsigned long hoseno = hose->pci_hose_index;
+ unsigned int stat0, temp, cpu;
+
+ cpu = smp_processor_id();
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+
+ draina();
+ MCPCIA_mcheck_expected[cpu] = 1;
+ mb();
+
+ /* Access configuration space. */
+ *((vuip)addr) = value;
+ mb();
+ mb(); /* magic */
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
+ MCPCIA_mcheck_expected[cpu] = 0;
+ mb();
+
+ DBG_CFG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+static int
+mk_conf_addr(struct linux_hose_info *hose,
+ u8 bus, u8 device_fn, u8 where,
+ unsigned long *pci_addr, unsigned char *type1)
+{
+ unsigned long addr;
+
+ if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */
+ return -1;
+
+ DBG_CFG(("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));
+
+ /* Type 1 configuration cycle for *ALL* busses. */
+ *type1 = 1;
+
+ if (hose->pci_first_busno == bus)
+ bus = 0;
+ addr = (bus << 16) | (device_fn << 8) | (where);
+ addr <<= 5; /* swizzle for SPARSE */
+ addr |= hose->pci_config_space;
+
+ *pci_addr = addr;
+ DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+/* FIXME: At some point we should update these routines to use the new
+ PCI interface, which can jump through these hoops for us. */
+
+static inline int
+hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x00;
+ *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x08;
+ *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x18;
+ *value = conf_read(addr, type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+mcpcia_pcibios_read_config_byte (u8 bus, u8 devfn, u8 where, u8 *value)
+{
+ return hose_read_config_byte(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_read_config_word (u8 bus, u8 devfn, u8 where, u16 *value)
+{
+ return hose_read_config_word(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_read_config_dword (u8 bus, u8 devfn, u8 where, u32 *value)
+{
+ return hose_read_config_dword(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_byte (u8 bus, u8 devfn, u8 where, u8 value)
+{
+ return hose_write_config_byte(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_word (u8 bus, u8 devfn, u8 where, u16 value)
+{
+ return hose_write_config_word(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_dword (u8 bus, u8 devfn, u8 where, u32 val)
+{
+ return hose_write_config_dword(bus, devfn, where, val, bus2hose[bus]);
+}
+
+void __init
+mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ struct linux_hose_info *hose;
+ unsigned int mcpcia_err;
+ unsigned int pci_rev;
+ int h;
+
+ *mem_start = long_align(*mem_start);
+
+ for (h = 0; h < NR_CPUS; h++) {
+ MCPCIA_mcheck_expected[h] = 0;
+ MCPCIA_mcheck_taken[h] = 0;
+ }
+
+ /* First, find how many hoses we have. */
+ for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
+ pci_rev = *(vuip)MCPCIA_REV(h);
+#if 0
+ printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n",
+ pci_rev, h);
+#endif
+ if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
+ mcpcia_num_hoses++;
+
+ hose = (struct linux_hose_info *)*mem_start;
+ *mem_start = long_align(*mem_start + sizeof(*hose));
+
+ memset(hose, 0, sizeof(*hose));
+
+ if (mcpcia_root)
+ mcpcia_last_hose->next = hose;
+ else
+ mcpcia_root = hose;
+ mcpcia_last_hose = hose;
+
+ hose->pci_io_space = MCPCIA_IO(h);
+ hose->pci_mem_space = MCPCIA_DENSE(h);
+ hose->pci_config_space = MCPCIA_CONF(h);
+ hose->pci_sparse_space = MCPCIA_SPARSE(h);
+ hose->pci_hose_index = h;
+ hose->pci_first_busno = 255;
+ hose->pci_last_busno = 0;
+ }
+ }
+
+#if 1
+ printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses);
+#endif
+
+ /* Now do init for each hose. */
+ for (hose = mcpcia_root; hose; hose = hose->next) {
+ h = hose->pci_hose_index;
+#if 0
+ printk("mcpcia_init: -------- hose %d --------\n",h);
+ printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
+ printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
+ printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
+ printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
+ printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
+ printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
+ printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
+ printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
+ printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
+ printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
+ printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
+ printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
+ printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
+#endif
+
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+#if 0
+ mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
+ mcpcia_err &= ~4;
+ *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
+ mb();
+ mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
+#endif
+
+ mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
+ mcpcia_err |= 0x0006; /* master/target abort */
+ *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
+ mb() ;
+ mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T0_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 0 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W0_BASE(h),
+ *(vuip)MCPCIA_W0_MASK(h),
+ *(vuip)MCPCIA_T0_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T1_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 1 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W1_BASE(h),
+ *(vuip)MCPCIA_W1_MASK(h),
+ *(vuip)MCPCIA_T1_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T2_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 2 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W2_BASE(h),
+ *(vuip)MCPCIA_W2_MASK(h),
+ *(vuip)MCPCIA_T2_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T3_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 3 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W3_BASE(h),
+ *(vuip)MCPCIA_W3_MASK(h),
+ *(vuip)MCPCIA_T3_BASE(h));
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
+ MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * 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)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)MCPCIA_T0_BASE(h) = 0;
+
+ *(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
+ *(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
+ *(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
+
+ *(vuip)MCPCIA_HBASE(h) = 0x0 ;
+ mb();
+ break;
+ }
+#if 0
+ {
+ unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
+ printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl);
+ *(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
+ mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
+ }
+#endif
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
+
+ alpha_mv.sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in mcpcia.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = mcpcia_hae_mem;
+
+ alpha_mv.mv_readb = mcpcia_srm_readb;
+ alpha_mv.mv_readw = mcpcia_srm_readw;
+ alpha_mv.mv_writeb = mcpcia_srm_writeb;
+ alpha_mv.mv_writew = mcpcia_srm_writew;
+ } else {
+ *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
+ *(vuip)MCPCIA_HAE_MEM(h); /* read it back. */
+ *(vuip)MCPCIA_HAE_IO(h) = 0; mb();
+ *(vuip)MCPCIA_HAE_IO(h); /* read it back. */
+ }
+ }
+}
+
+static int
+mcpcia_pci_clr_err(int h)
+{
+ unsigned int cpu = smp_processor_id();
+
+ MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
+#if 0
+ DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
+ h, MCPCIA_jd[cpu]));
+#endif
+ *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
+ MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
+ return 0;
+}
+
+static void
+mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
+{
+ struct el_common_EV5_uncorrectable_mcheck *frame;
+ int i;
+
+ frame = &logout->procdata;
+
+ /* Print PAL fields */
+ for (i = 0; i < 24; i += 2) {
+ printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r",
+ i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
+ }
+ for (i = 0; i < 8; i += 2) {
+ printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r",
+ i, i+1, frame->shadow[i],
+ frame->shadow[i+1]);
+ }
+ printk("\tAddr of excepting instruction\t= %16lx\n\r",
+ frame->exc_addr);
+ printk("\tSummary of arithmetic traps\t= %16lx\n\r",
+ frame->exc_sum);
+ printk("\tException mask\t\t\t= %16lx\n\r",
+ frame->exc_mask);
+ printk("\tBase address for PALcode\t= %16lx\n\r",
+ frame->pal_base);
+ printk("\tInterrupt Status Reg\t\t= %16lx\n\r",
+ frame->isr);
+ printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r",
+ frame->icsr);
+ printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r",
+ (frame->ic_perr_stat & 0x800L) ?
+ "Data" : "Tag",
+ frame->ic_perr_stat);
+ printk("\tD-CACHE error Reg\t\t= %16lx\n\r",
+ frame->dc_perr_stat);
+ if (frame->dc_perr_stat & 0x2) {
+ switch (frame->dc_perr_stat & 0x03c) {
+ case 8:
+ printk("\t\tData error in bank 1\n\r");
+ break;
+ case 4:
+ printk("\t\tData error in bank 0\n\r");
+ break;
+ case 20:
+ printk("\t\tTag error in bank 1\n\r");
+ break;
+ case 10:
+ printk("\t\tTag error in bank 0\n\r");
+ break;
+ }
+ }
+ printk("\tEffective VA\t\t\t= %16lx\n\r",
+ frame->va);
+ printk("\tReason for D-stream\t\t= %16lx\n\r",
+ frame->mm_stat);
+ printk("\tEV5 SCache address\t\t= %16lx\n\r",
+ frame->sc_addr);
+ printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r",
+ frame->sc_stat);
+ printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r",
+ frame->bc_tag_addr);
+ printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r",
+ frame->ei_addr);
+ printk("\tFill Syndrome\t\t\t= %16lx\n\r",
+ frame->fill_syndrome);
+ printk("\tEI_STAT reg\t\t\t= %16lx\n\r",
+ frame->ei_stat);
+ printk("\tLD_LOCK\t\t\t\t= %16lx\n\r",
+ frame->ld_lock);
+}
+
+void
+mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#if 0
+ printk("mcpcia machine check ignored\n") ;
+#else
+ struct el_common *mchk_header;
+ struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
+ unsigned int cpu = smp_processor_id();
+ int h = 0;
+
+ mchk_header = (struct el_common *)la_ptr;
+ mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
+
+#if 0
+ DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
+ type, la_ptr));
+ DBG_MCK(("\t\t 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));
+#endif
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (MCPCIA_mcheck_expected[cpu]) {
+#if 0
+ DBG_MCK(("MCPCIA machine check expected\n"));
+#endif
+ MCPCIA_mcheck_expected[cpu] = 0;
+ MCPCIA_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ mcpcia_pci_clr_err(h);
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
+ DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
+ " code=0x%lx\n",
+ type, regs->pc, mchk_header->code));
+
+ MCPCIA_mcheck_expected[cpu] = 0;
+ MCPCIA_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ mcpcia_pci_clr_err(h);
+ wrmces(0x7);
+ mb();
+#ifdef DEBUG_MCHECK_DUMP
+ if (type == 0x620)
+ printk("MCPCIA machine check: system CORRECTABLE!\n");
+ else if (type == 0x630)
+ printk("MCPCIA machine check: processor CORRECTABLE!\n");
+ else
+ mcpcia_print_uncorrectable(mchk_logout);
+#endif /* DEBUG_MCHECK_DUMP */
+ }
+#endif
+#endif
+}
+
+/*==========================================================================*/
+
+#define PRIMARY(b) ((b)&0xff)
+#define SECONDARY(b) (((b)>>8)&0xff)
+#define SUBORDINATE(b) (((b)>>16)&0xff)
+
+static int __init
+hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int devfn, l, class;
+ unsigned char hdr_type = 0;
+ unsigned int found = 0;
+
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ if (PCI_FUNC(devfn) == 0) {
+ hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE,
+ &hdr_type, hose);
+ } else if (!(hdr_type & 0x80)) {
+ /* not a multi-function device */
+ continue;
+ }
+
+ /* Check if there is anything here. */
+ hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose);
+ if (l == 0xffffffff || l == 0x00000000) {
+ hdr_type = 0;
+ continue;
+ }
+
+ /* See if this is a bridge device. */
+ hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
+ &class, hose);
+
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ unsigned int busses;
+
+ found++;
+
+ hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ &busses, hose);
+
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d busses 0x%x\n",
+ hose->pci_hose_index, bus, PCI_SLOT(devfn),
+ busses));
+
+ /*
+ * Do something with first_busno and last_busno
+ */
+ if (hose->pci_first_busno > PRIMARY(busses)) {
+ hose->pci_first_busno = PRIMARY(busses);
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d change first to %d\n",
+ hose->pci_hose_index, bus,
+ PCI_SLOT(devfn), PRIMARY(busses)));
+ }
+ if (hose->pci_last_busno < SUBORDINATE(busses)) {
+ hose->pci_last_busno = SUBORDINATE(busses);
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d change last to %d\n",
+ hose->pci_hose_index, bus,
+ PCI_SLOT(devfn),
+ SUBORDINATE(busses)));
+ }
+ /*
+ * Now scan everything underneath the bridge.
+ */
+ hose_scan_bridges(hose, SECONDARY(busses));
+ }
+ }
+ return found;
+}
+
+static void __init
+hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int devfn, l, class;
+ unsigned char hdr_type = 0;
+
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ if (PCI_FUNC(devfn) == 0) {
+ hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE,
+ &hdr_type, hose);
+ } else if (!(hdr_type & 0x80)) {
+ /* not a multi-function device */
+ continue;
+ }
+
+ /* Check if there is anything here. */
+ hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose);
+ if (l == 0xffffffff || l == 0x00000000) {
+ hdr_type = 0;
+ continue;
+ }
+
+ /* See if this is a bridge device. */
+ hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
+ &class, hose);
+
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ unsigned int busses;
+
+ hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ &busses, hose);
+
+ /*
+ * First reconfigure everything underneath the bridge.
+ */
+ hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
+
+ /*
+ * Unconfigure this bridges bus numbers,
+ * pci_scan_bus() will fix this up properly.
+ */
+ busses &= 0xff000000;
+ hose_write_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ busses, hose);
+ }
+ }
+}
+
+static void __init
+mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int nbus;
+
+ /*
+ * First, scan for all bridge devices underneath this hose,
+ * to determine the first and last busnos.
+ */
+ if (!hose_scan_bridges(hose, 0)) {
+ /* none found, exit */
+ hose->pci_first_busno = bus;
+ hose->pci_last_busno = bus;
+ } else {
+ /*
+ * Reconfigure all bridge devices underneath this hose.
+ */
+ hose_reconfigure_bridges(hose, hose->pci_first_busno);
+ }
+
+ /*
+ * Now reconfigure the hose to it's new bus number and set up
+ * our bus2hose mapping for this hose.
+ */
+ nbus = hose->pci_last_busno - hose->pci_first_busno;
+
+ hose->pci_first_busno = bus;
+
+ DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n",
+ hose->pci_hose_index, bus, nbus));
+
+ do {
+ bus2hose[bus++] = hose;
+ } while (nbus-- > 0);
+}
+
+static void __init
+mcpcia_probe(struct linux_hose_info *hose)
+{
+ static struct pci_bus *pchain = NULL;
+ struct pci_bus *pbus = &hose->pci_bus;
+ static unsigned char busno = 0;
+
+ /*
+ * Hoses include child PCI bridges in bus-range property,
+ * but we don't scan each of those ourselves, Linux generic PCI
+ * probing code will find child bridges and link them into this
+ * hose's root PCI device hierarchy.
+ */
+
+ pbus->number = pbus->secondary = busno;
+ pbus->sysdata = hose;
+
+ mcpcia_fixup_busno(hose, busno);
+
+ pbus->subordinate = pci_scan_bus(pbus); /* the original! */
+
+ /*
+ * Set the maximum subordinate bus of this hose.
+ */
+ hose->pci_last_busno = pbus->subordinate;
+#if 0
+ hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno, hose);
+#endif
+ busno = pbus->subordinate + 1;
+
+ /*
+ * Fixup the chain of primary PCI busses.
+ */
+ if (pchain) {
+ pchain->next = &hose->pci_bus;
+ pchain = pchain->next;
+ } else {
+ pchain = &pci_root;
+ memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
+ }
+}
+
+void __init
+mcpcia_pci_fixup(void)
+{
+ struct linux_hose_info *hose;
+
+ /* Turn on Config space access finally! */
+ pci_probe_enabled = 1;
+
+ /* For each hose, probe and setup the devices on the hose. */
+ for (hose = mcpcia_root; hose; hose = hose->next)
+ mcpcia_probe(hose);
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_pyxis.c
+ *
+ * Code common to all PYXIS core logic chips.
+ *
+ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_pyxis.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/* NOTE: Herein are back-to-back mb instructions. They are magic.
+ One plausible explanation is that the I/O controller does not properly
+ handle the system transaction. Another involves timing. Ho hum. */
+
+extern asmlinkage void wrmces(unsigned long mces);
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+#define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+
+static volatile unsigned int PYXIS_mcheck_expected = 0;
+static volatile unsigned int PYXIS_mcheck_taken = 0;
+static unsigned int PYXIS_jd;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the PYXIS_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(u8 bus, u8 device_fn, u8 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 = device_fn >> 3;
+ /* Type 0 configuration cycle. */
+#if NOT_NOW
+ if (device > 20) {
+ DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
+ device));
+ return -1;
+ }
+#endif
+ *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, temp;
+ unsigned int pyxis_cfg = 0;
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = stat0; mb();
+ temp = *(vuip)PYXIS_ERR; /* re-read to force write */
+ DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set PYXIS CFG. */
+ if (type1) {
+ pyxis_cfg = *(vuip)PYXIS_CFG;
+ *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ mb();
+ draina();
+ PYXIS_mcheck_expected = 1;
+ PYXIS_mcheck_taken = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *(vuip)addr;
+ mb();
+ mb(); /* magic */
+
+ if (PYXIS_mcheck_taken) {
+ PYXIS_mcheck_taken = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ PYXIS_mcheck_expected = 0;
+ mb();
+
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
+ if (type1) {
+ *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+
+ 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, temp;
+ unsigned int pyxis_cfg = 0;
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = stat0; mb();
+ temp = *(vuip)PYXIS_ERR; /* re-read to force write */
+ DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set PYXIS CFG. */
+ if (type1) {
+ pyxis_cfg = *(vuip)PYXIS_CFG;
+ *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ draina();
+ PYXIS_mcheck_expected = 1;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ mb();
+ mb(); /* magic */
+ temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */
+ PYXIS_mcheck_expected = 0;
+ mb();
+
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
+ if (type1) {
+ *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+
+ DBG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+int
+pyxis_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = PYXIS_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = PYXIS_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+pyxis_enable_errors (void)
+{
+ unsigned int pyxis_err;
+
+#if 0
+ printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
+ printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR);
+ printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ);
+ printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK);
+ printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE);
+ printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO);
+ printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG);
+ printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT);
+#endif
+
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+ pyxis_err = *(vuip)PYXIS_ERR_MASK;
+ pyxis_err &= ~4;
+ *(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
+ pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
+
+ pyxis_err = *(vuip)PYXIS_ERR ;
+ pyxis_err |= 0x180; /* master/target abort */
+ *(vuip)PYXIS_ERR = pyxis_err; mb();
+ pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
+}
+
+int __init
+pyxis_srm_window_setup (void)
+{
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W0_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T0_BASE == 0)
+ && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 0 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W0_BASE,
+ *(vuip)PYXIS_W0_MASK,
+ *(vuip)PYXIS_T0_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W1_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T1_BASE == 0)
+ && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 1 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W1_BASE,
+ *(vuip)PYXIS_W1_MASK,
+ *(vuip)PYXIS_T1_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W2_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T2_BASE == 0)
+ && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 2 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W2_BASE,
+ *(vuip)PYXIS_W2_MASK,
+ *(vuip)PYXIS_T2_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W3_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T3_BASE == 0)
+ && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 3 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W3_BASE,
+ *(vuip)PYXIS_W3_MASK,
+ *(vuip)PYXIS_T3_BASE);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
+ PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ return 0;
+ }
+ return 1;
+}
+
+void __init
+pyxis_native_window_setup(void)
+{
+ /*
+ * 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)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)PYXIS_T0_BASE = 0;
+
+ *(vuip)PYXIS_W1_BASE = 0x0 ;
+ *(vuip)PYXIS_W2_BASE = 0x0 ;
+ *(vuip)PYXIS_W3_BASE = 0x0 ;
+ mb();
+}
+
+void __init
+pyxis_finish_init_arch(void)
+{
+ /*
+ * Next, clear the PYXIS_CFG register, which gets used
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
+ */
+ {
+ unsigned int pyxis_cfg, temp;
+ pyxis_cfg = *(vuip)PYXIS_CFG; mb();
+ if (pyxis_cfg != 0) {
+#if 1
+ printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg);
+#endif
+ *(vuip)PYXIS_CFG = 0; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+ }
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/pyxis.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
+
+ alpha_mv.sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in pyxis.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = pyxis_hae_mem;
+
+#ifndef CONFIG_ALPHA_GENERIC
+ /* In a generic kernel, we can always use BWIO. */
+ alpha_mv.mv_readb = pyxis_srm_readb;
+ alpha_mv.mv_readw = pyxis_srm_readw;
+ alpha_mv.mv_writeb = pyxis_srm_writeb;
+ alpha_mv.mv_writew = pyxis_srm_writew;
+#endif
+ } else {
+ *(vuip)PYXIS_HAE_MEM = 0U; mb();
+ *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
+ *(vuip)PYXIS_HAE_IO = 0; mb();
+ *(vuip)PYXIS_HAE_IO; /* re-read to force write */
+ }
+
+ /*
+ * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
+ * enabling byte/word PCI bus space(s) access.
+ */
+ {
+ unsigned int ctrl1;
+ ctrl1 = *(vuip) PYXIS_CTRL1;
+ if (!(ctrl1 & 1)) {
+#if 1
+ printk("PYXIS_init: enabling byte/word PCI space\n");
+#endif
+ *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb();
+ ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read */
+ }
+ }
+}
+
+void __init
+pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ pyxis_enable_errors();
+ if (!pyxis_srm_window_setup())
+ pyxis_native_window_setup();
+ pyxis_finish_init_arch();
+}
+
+static int
+pyxis_pci_clr_err(void)
+{
+ PYXIS_jd = *(vuip)PYXIS_ERR;
+ DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
+ *(vuip)PYXIS_ERR = 0x0180; mb();
+ PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */
+ return 0;
+}
+
+void
+pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_common *mchk_header;
+ struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#if 0
+ DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t 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_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+ {
+ 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_MCHECK_DUMP */
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (PYXIS_mcheck_expected) {
+ DBG(("PYXIS machine check expected\n"));
+ PYXIS_mcheck_expected = 0;
+ PYXIS_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ pyxis_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("PYXIS machine check NOT expected\n") ;
+ DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t 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));
+ PYXIS_mcheck_expected = 0;
+ PYXIS_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ pyxis_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#endif
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_t2.c
+ *
+ * Code common to all T2 core logic chips.
+ *
+ * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
+ * December 1996.
+ *
+ * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE
+#include <asm/io.h>
+#include <asm/core_t2.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+/*
+ * Machine check reasons. Defined according to PALcode sources
+ * (osf.h and platform.h).
+ */
+#define MCHK_K_TPERR 0x0080
+#define MCHK_K_TCPERR 0x0082
+#define MCHK_K_HERR 0x0084
+#define MCHK_K_ECC_C 0x0086
+#define MCHK_K_ECC_NC 0x0088
+#define MCHK_K_OS_BUGCHECK 0x008A
+#define MCHK_K_PAL_BUGCHECK 0x0090
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG_CONF
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#ifdef DEBUG_MCHECK
+# define DBGMC(args) printk args
+#else
+# define DBGMC(args)
+#endif
+
+static volatile unsigned int T2_mcheck_expected[NR_CPUS];
+static volatile unsigned int T2_mcheck_taken[NR_CPUS];
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the T2_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(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+
+ DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x,"
+ " addr=0x%lx, type1=0x%x)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ if (bus == 0) {
+ int device = device_fn >> 3;
+
+ /* Type 0 configuration cycle. */
+
+ if (device > 8) {
+ DBG(("mk_conf_addr: device (%d)>20, returning -1\n",
+ device));
+ return -1;
+ }
+
+ *type1 = 0;
+ addr = (0x0800L << device) | ((device_fn & 7) << 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, cpu;
+ unsigned long t2_cfg = 0;
+
+ cpu = smp_processor_id();
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+#if 0
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vulp)T2_IOCSR;
+ *(vulp)T2_IOCSR = stat0;
+ mb();
+ DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
+#endif
+
+ /* If Type1 access, must set T2 CFG. */
+ if (type1) {
+ t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
+ *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
+ mb();
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+ mb();
+ draina();
+
+ T2_mcheck_expected[cpu] = 1;
+ T2_mcheck_taken[cpu] = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *(vuip)addr;
+ mb();
+ mb(); /* magic */
+
+ if (T2_mcheck_taken[cpu]) {
+ T2_mcheck_taken[cpu] = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ T2_mcheck_expected[cpu] = 0;
+ mb();
+
+ /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
+ if (type1) {
+ *(vulp)T2_HAE_3 = t2_cfg;
+ 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, cpu;
+ unsigned long t2_cfg = 0;
+
+ cpu = smp_processor_id();
+
+ save_flags(flags); /* avoid getting hit by machine check */
+ cli();
+
+#if 0
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vulp)T2_IOCSR;
+ *(vulp)T2_IOCSR = stat0;
+ mb();
+ DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
+#endif
+
+ /* If Type1 access, must set T2 CFG. */
+ if (type1) {
+ t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
+ *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
+ mb();
+ DBG(("conf_write: TYPE1 access\n"));
+ }
+ mb();
+ draina();
+
+ T2_mcheck_expected[cpu] = 1;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ mb();
+ mb(); /* magic */
+
+ T2_mcheck_expected[cpu] = 0;
+ mb();
+
+ /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
+ if (type1) {
+ *(vulp)T2_HAE_3 = t2_cfg;
+ mb();
+ }
+ DBG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+
+int
+t2_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = T2_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+t2_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = T2_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+t2_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = T2_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_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+t2_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = T2_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+t2_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = T2_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+t2_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = T2_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ unsigned long t2_err;
+ unsigned int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ T2_mcheck_expected[i] = 0;
+ T2_mcheck_taken[i] = 0;
+ }
+
+#if 0
+ /*
+ * Set up error reporting.
+ */
+ t2_err = *(vulp)T2_IOCSR ;
+ t2_err |= (0x1 << 7) ; /* master abort */
+ *(vulp)T2_IOCSR = t2_err ;
+ mb() ;
+#endif
+
+ printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE);
+#if 0
+ printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
+ *(vulp)T2_WBASE1,
+ *(vulp)T2_WMASK1,
+ *(vulp)T2_TBASE1);
+ printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
+ *(vulp)T2_WBASE2,
+ *(vulp)T2_WMASK2,
+ *(vulp)T2_TBASE2);
+#endif
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18))
+ && (*(vulp)T2_TBASE1 == 0)) {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+ /* DISABLE window 2!! ?? */
+#if 1
+ printk("t2_init: using Window 1 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE1,
+ *(vulp)T2_WMASK1,
+ *(vulp)T2_TBASE1);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18))
+ && (*(vulp)T2_TBASE2 == 0)) {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+ /* DISABLE window 1!! ?? */
+#if 1
+ printk("t2_init: using Window 2 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE2,
+ *(vulp)T2_WMASK2,
+ *(vulp)T2_TBASE2);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
+ T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 1 goes at 1 GB and is 1 GB large.
+ */
+
+ /* WARNING!! must correspond to the DMA_WIN params!!! */
+ *(vulp)T2_WBASE1 = 0x400807ffU;
+ *(vulp)T2_WMASK1 = 0x3ff00000U;
+ *(vulp)T2_TBASE1 = 0;
+
+ *(vulp)T2_WBASE2 = 0x0;
+ *(vulp)T2_HBASE = 0x0;
+ break;
+ }
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/t2.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
+
+ alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in .h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = t2_hae_1;
+
+ alpha_mv.mv_readb = t2_srm_readb;
+ alpha_mv.mv_readw = t2_srm_readw;
+ alpha_mv.mv_writeb = t2_srm_writeb;
+ alpha_mv.mv_writew = t2_srm_writew;
+ } else {
+ *(vulp)T2_HAE_1 = 0; mb();
+ *(vulp)T2_HAE_2 = 0; mb();
+ *(vulp)T2_HAE_3 = 0; mb();
+#if 0
+ *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
+#endif
+ }
+}
+
+#define SIC_SEIC (1UL << 33) /* System Event Clear */
+
+static int
+t2_clear_errors(void)
+{
+ unsigned int cpu = smp_processor_id();
+ static struct sable_cpu_csr *cpu_regs = NULL;
+
+ switch (cpu)
+ {
+ case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break;
+ case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break;
+ case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break;
+ case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break;
+ }
+
+ DBGMC(("???????? t2_clear_errors\n"));
+
+ cpu_regs->sic &= ~SIC_SEIC;
+
+ /*
+ * clear CPU errors
+ */
+ cpu_regs->bcce |= cpu_regs->bcce;
+ cpu_regs->cbe |= cpu_regs->cbe;
+ cpu_regs->bcue |= cpu_regs->bcue;
+ cpu_regs->dter |= cpu_regs->dter;
+
+ *(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
+ *(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
+
+ mb();
+ mb(); /* magic */
+ return 0;
+}
+
+void
+t2_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_t2_logout_header *mchk_header;
+ struct el_t2_procdata_mcheck *mchk_procdata;
+ struct el_t2_sysdata_mcheck *mchk_sysdata;
+ unsigned long * ptr;
+ const char * reason;
+ char buf[128];
+ long i;
+ unsigned int cpu = smp_processor_id();
+
+ DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+
+ mchk_header = (struct el_t2_logout_header *)la_ptr;
+
+ DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n",
+ mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset));
+
+ mchk_sysdata = (struct el_t2_sysdata_mcheck *)
+ (la_ptr + mchk_header->elfl_sysoffset);
+ mchk_procdata = (struct el_t2_procdata_mcheck *)
+ (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
+
+ DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
+ mchk_header->elfl_sysoffset));
+ DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu]));
+
+#ifdef DEBUG_DUMP
+ {
+ unsigned long *ptr;
+ int i;
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long),
+ ptr[i], ptr[i+1]);
+ }
+ }
+#endif /* DEBUG_DUMP */
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (T2_mcheck_expected[cpu]) {
+ DBGMC(("T2 machine check expected\n"));
+ T2_mcheck_taken[cpu] = 1;
+ t2_clear_errors();
+ T2_mcheck_expected[cpu] = 0;
+ mb();
+ mb(); /* magic */
+ wrmces(rdmces()|1);/* ??? */
+ draina();
+ return;
+ }
+
+ switch ((unsigned int) mchk_header->elfl_error_type) {
+ case MCHK_K_TPERR: reason = "tag parity error"; break;
+ case MCHK_K_TCPERR: reason = "tag control parity error"; break;
+ case MCHK_K_HERR: reason = "generic hard error"; break;
+ case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
+ case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
+ case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
+ case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
+ case 0x96: reason = "i-cache read retryable error"; break;
+ case 0x98: reason = "processor detected hard error"; break;
+
+ /* System specific (these are for Alcor, at least): */
+ case 0x203: reason = "system detected uncorrectable ECC error"; break;
+ case 0x205: reason = "parity error detected by T2"; break;
+ case 0x207: reason = "non-existent memory error"; break;
+ case 0x209: reason = "PCI SERR detected"; break;
+ case 0x20b: reason = "PCI data parity error detected"; break;
+ case 0x20d: reason = "PCI address parity error detected"; break;
+ case 0x20f: reason = "PCI master abort error"; break;
+ case 0x211: reason = "PCI target abort error"; break;
+ case 0x213: reason = "scatter/gather PTE invalid error"; break;
+ case 0x215: reason = "flash ROM write error"; break;
+ case 0x217: reason = "IOA timeout detected"; break;
+ case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
+ case 0x21b: reason = "EISA fail-safe timer timeout"; break;
+ case 0x21d: reason = "EISA bus time-out"; break;
+ case 0x21f: reason = "EISA software generated NMI"; break;
+ case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
+ default:
+ sprintf(buf, "reason for machine-check unknown (0x%x)",
+ (unsigned int) mchk_header->elfl_error_type);
+ reason = buf;
+ break;
+ }
+ wrmces(rdmces()|1); /* reset machine check pending flag */
+ mb();
+
+ printk(KERN_CRIT " T2 machine check: %s%s\n",
+ reason, mchk_header->elfl_retry ? " (retryable)" : "");
+
+ /* Dump the logout area to give all info. */
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/core_tsunami.c
+ *
+ * Code common to all TSUNAMI core logic chips.
+ *
+ * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_tsunami.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the I/O controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+#define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
+static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
+static unsigned int TSUNAMI_jd[NR_CPUS];
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address
+ * 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.
+ *
+ * Note that all config space accesses use Type 1 address format.
+ *
+ * Note also that type 1 is determined by non-zero bus 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(u8 bus, u8 device_fn, u8 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) {
+ *type1 = 0;
+ } 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;
+}
+
+int
+tsunami_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xff;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = *(vuip)(addr+TSUNAMI_PCI0_CONF);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stb(value, *(vucp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stw(value, *(vusp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *(vuip)(addr+TSUNAMI_PCI0_CONF) = value;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ unsigned long tsunami_err;
+ unsigned int i;
+
+#if 0
+ printk("tsunami_init: CChip registers:\n");
+ printk("CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC);
+ printk("CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR);
+ printk("CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC);
+ printk("CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0);
+ printk("CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1);
+ printk("CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0);
+ printk("CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1);
+ printk("CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR);
+
+ printk("tsunami_init: DChip registers:\n");
+ printk("CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC);
+ printk("CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR);
+ printk("CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV);
+
+ printk("tsunami_init: PChip registers:\n");
+ printk("PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0);
+ printk("PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1);
+ printk("PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2);
+ printk("PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3);
+ printk("PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0);
+ printk("PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1);
+ printk("PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2);
+ printk("PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3);
+ printk("PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0);
+ printk("PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1);
+ printk("PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2);
+ printk("PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3);
+ printk("PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL);
+ printk("PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT);
+ printk("PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR);
+ printk("PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK);
+#endif
+
+ for (i = 0; i < NR_CPUS; i++) {
+ TSUNAMI_mcheck_expected[i] = 0;
+ TSUNAMI_mcheck_taken[i] = 0;
+ }
+
+#ifdef NOT_YET
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
+ tsunami_err &= ~20;
+ *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err;
+ mb();
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
+
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
+ tsunami_err |= 0x40; /* master/target abort */
+ *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ;
+ mb() ;
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
+#endif /* NOT_YET */
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 0 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA0,
+ *(vulp)TSUNAMI_PCHIP0_WSM0,
+ *(vulp)TSUNAMI_PCHIP0_TBA0);
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 1 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA1,
+ *(vulp)TSUNAMI_PCHIP0_WSM1,
+ *(vulp)TSUNAMI_PCHIP0_TBA1);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA2 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 2 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA2,
+ *(vulp)TSUNAMI_PCHIP0_WSM2,
+ *(vulp)TSUNAMI_PCHIP0_TBA2);
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 3 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA3,
+ *(vulp)TSUNAMI_PCHIP0_WSM3,
+ *(vulp)TSUNAMI_PCHIP0_TBA3);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
+ TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * 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.
+ */
+
+ *(vulp)TSUNAMI_PCHIP0_WSBA0
+ = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vulp)TSUNAMI_PCHIP0_WSM0
+ = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL;
+ *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL;
+
+ *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL;
+ *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL;
+ *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL;
+ mb();
+ }
+}
+
+static int
+tsunami_pci_clr_err(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
+ DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n",TSUNAMI_jd[cpu]));
+ *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb();
+ TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
+ return 0;
+}
+
+void
+tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#if 1
+ printk("TSUNAMI machine check ignored\n") ;
+#else
+ struct el_common *mchk_header;
+ struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
+ unsigned int cpu = smp_processor_id();
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#if 0
+ DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t 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_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+ {
+ 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_MCHECK_DUMP */
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (TSUNAMI_mcheck_expected[cpu]) {
+ DBG(("TSUNAMI machine check expected\n"));
+ TSUNAMI_mcheck_expected[cpu] = 0;
+ TSUNAMI_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ tsunami_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("TSUNAMI machine check NOT expected\n") ;
+ DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t 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));
+ TSUNAMI_mcheck_expected[cpu] = 0;
+ TSUNAMI_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ tsunami_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#endif
+#endif
+}
#define osf_vfork sys_fork
/*
- * These offsets must match with "struct hae" in io.h:
+ * These offsets must match with alpha_mv in <asm/machvec.h>.
*/
#define HAE_CACHE 0
#define HAE_REG 8
stq $3,24($30); \
stq $4,32($30); \
stq $28,144($30); \
- lda $2,hae; \
+ lda $2,alpha_mv; \
stq $5,40($30); \
stq $6,48($30); \
stq $7,56($30); \
stq $18,176($30)
#define RESTORE_ALL \
- lda $19,hae; \
+ lda $19,alpha_mv; \
ldq $0,0($30); \
ldq $1,8($30); \
ldq $2,16($30); \
.quad sys_sysinfo
.quad sys_sysctl
.quad sys_idle /* 320 */
- .quad sys_umount
+ .quad sys_oldumount
.quad sys_swapon
.quad sys_times
.quad sys_personality
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/es1888.c
+ *
+ * Init the built-in ES1888 sound chip (SB16 compatible)
+ */
+
+#include <linux/init.h>
+#include <asm/io.h>
+#include "proto.h"
+
+void __init
+es1888_init(void)
+{
+ /* Sequence of IO reads to init the audio controller */
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x0220); /* This sets the base address to 0x220 */
+
+ /* Sequence to set DMA channels */
+ outb(0x01, 0x0226); /* reset */
+ inb(0x0226); /* pause */
+ outb(0x00, 0x0226); /* release reset */
+ while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
+ continue;
+ inb(0x022a); /* pause */
+ outb(0xc6, 0x022c); /* enable extended mode */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0x14, 0x022c); /* set IRQ 5 */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0xb2, 0x022c); /* setup for write to DMA CR */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0x18, 0x022c); /* set DMA channel 1 */
+}
* (C) Copyright 1998 Linus Torvalds
*/
+#ifdef __alpha_cix__
+#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
+#else
+#define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val));
+#endif
+
unsigned long
alpha_read_fp_reg (unsigned long reg)
{
- unsigned long r;
+ unsigned long val;
switch (reg) {
- case 0: asm ("stt $f0,%0" : "m="(r)); break;
- case 1: asm ("stt $f1,%0" : "m="(r)); break;
- case 2: asm ("stt $f2,%0" : "m="(r)); break;
- case 3: asm ("stt $f3,%0" : "m="(r)); break;
- case 4: asm ("stt $f4,%0" : "m="(r)); break;
- case 5: asm ("stt $f5,%0" : "m="(r)); break;
- case 6: asm ("stt $f6,%0" : "m="(r)); break;
- case 7: asm ("stt $f7,%0" : "m="(r)); break;
- case 8: asm ("stt $f8,%0" : "m="(r)); break;
- case 9: asm ("stt $f9,%0" : "m="(r)); break;
- case 10: asm ("stt $f10,%0" : "m="(r)); break;
- case 11: asm ("stt $f11,%0" : "m="(r)); break;
- case 12: asm ("stt $f12,%0" : "m="(r)); break;
- case 13: asm ("stt $f13,%0" : "m="(r)); break;
- case 14: asm ("stt $f14,%0" : "m="(r)); break;
- case 15: asm ("stt $f15,%0" : "m="(r)); break;
- case 16: asm ("stt $f16,%0" : "m="(r)); break;
- case 17: asm ("stt $f17,%0" : "m="(r)); break;
- case 18: asm ("stt $f18,%0" : "m="(r)); break;
- case 19: asm ("stt $f19,%0" : "m="(r)); break;
- case 20: asm ("stt $f20,%0" : "m="(r)); break;
- case 21: asm ("stt $f21,%0" : "m="(r)); break;
- case 22: asm ("stt $f22,%0" : "m="(r)); break;
- case 23: asm ("stt $f23,%0" : "m="(r)); break;
- case 24: asm ("stt $f24,%0" : "m="(r)); break;
- case 25: asm ("stt $f25,%0" : "m="(r)); break;
- case 26: asm ("stt $f26,%0" : "m="(r)); break;
- case 27: asm ("stt $f27,%0" : "m="(r)); break;
- case 28: asm ("stt $f28,%0" : "m="(r)); break;
- case 29: asm ("stt $f29,%0" : "m="(r)); break;
- case 30: asm ("stt $f30,%0" : "m="(r)); break;
- case 31: asm ("stt $f31,%0" : "m="(r)); break;
- default:
- break;
+ case 0: STT( 0, val); break;
+ case 1: STT( 1, val); break;
+ case 2: STT( 2, val); break;
+ case 3: STT( 3, val); break;
+ case 4: STT( 4, val); break;
+ case 5: STT( 5, val); break;
+ case 6: STT( 6, val); break;
+ case 7: STT( 7, val); break;
+ case 8: STT( 8, val); break;
+ case 9: STT( 9, val); break;
+ case 10: STT(10, val); break;
+ case 11: STT(11, val); break;
+ case 12: STT(12, val); break;
+ case 13: STT(13, val); break;
+ case 14: STT(14, val); break;
+ case 15: STT(15, val); break;
+ case 16: STT(16, val); break;
+ case 17: STT(17, val); break;
+ case 18: STT(18, val); break;
+ case 19: STT(19, val); break;
+ case 20: STT(20, val); break;
+ case 21: STT(21, val); break;
+ case 22: STT(22, val); break;
+ case 23: STT(23, val); break;
+ case 24: STT(24, val); break;
+ case 25: STT(25, val); break;
+ case 26: STT(26, val); break;
+ case 27: STT(27, val); break;
+ case 28: STT(28, val); break;
+ case 29: STT(29, val); break;
+ case 30: STT(30, val); break;
+ case 31: STT(31, val); break;
}
- return r;
+ return val;
}
-#if 1
-/*
- * This is IMHO the better way of implementing LDT(). But it
- * has the disadvantage that gcc 2.7.0 refuses to compile it
- * (invalid operand constraints), so instead, we use the uglier
- * macro below.
- */
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",%0" : : "m"(val));
+#ifdef __alpha_cix__
+#define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val));
#else
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",0(%0)" : : "r"(&val));
+#define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val));
#endif
void
case 29: LDT(29, val); break;
case 30: LDT(30, val); break;
case 31: LDT(31, val); break;
- default:
- break;
}
}
* the kernel global pointer and jump to the kernel entry-point.
*/
-#define __ASSEMBLY__
#include <asm/system.h>
#define halt call_pal PAL_halt
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
-#include <asm/dma.h>
+#include <asm/machvec.h>
+
+#include "proto.h"
+#include "irq.h"
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
-extern void timer_interrupt(struct pt_regs * regs);
-extern void cserve_update_hw(unsigned long, unsigned long);
-extern void handle_ipi(struct pt_regs *);
+unsigned int local_irq_count[NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+
#define RTC_IRQ 8
#ifdef CONFIG_RTC
# error Unable to handle more than 64 irq levels.
#endif
-/* PROBE_MASK is the bitset of irqs that we consider for autoprobing: */
-#if defined(CONFIG_ALPHA_P2K)
- /* always mask out unused timer irq 0 and RTC irq 8 */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0x101UL)
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- /* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL)
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- /* must leave timer irq 0 in the mask */
-# define PROBE_MASK ((1UL << NR_IRQS) - 1)
-#elif NR_IRQS == 64
- /* always mask out unused timer irq 0: */
-# define PROBE_MASK (~1UL)
+#ifdef CONFIG_ALPHA_GENERIC
+#define ACTUAL_NR_IRQS alpha_mv.nr_irqs
#else
- /* always mask out unused timer irq 0: */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL)
+#define ACTUAL_NR_IRQS NR_IRQS
#endif
/* Reserved interrupts. These must NEVER be requested by any driver!
- */
-#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */
+ IRQ 2 used by hw cascade */
+#define IS_RESERVED_IRQ(irq) ((irq)==2)
-/*
- * Shadow-copy of masked interrupts.
- * The bits are used as follows:
- * 0.. 7 first (E)ISA PIC (irq level 0..7)
- * 8..15 second (E)ISA PIC (irq level 8..15)
- * Systems with PCI interrupt lines managed by GRU (e.g., Alcor, XLT)
- * or PYXIS (e.g. Miata, PC164-LX):
- * 16..47 PCI interrupts 0..31 (int at xxx_INT_MASK)
- * Mikasa:
- * 16..31 PCI interrupts 0..15 (short at I/O port 536)
- * Other systems (not Mikasa) with 16 PCI interrupt lines:
- * 16..23 PCI interrupts 0.. 7 (char at I/O port 26)
- * 24..31 PCI interrupts 8..15 (char at I/O port 27)
- * Systems with 17 PCI interrupt lines (e.g., Cabriolet and eb164):
- * 16..32 PCI interrupts 0..31 (int at I/O port 804)
- * For SABLE, which is really baroque, we manage 40 IRQ's, but the
- * hardware really only supports 24, not via normal ISA PIC,
- * but cascaded custom 8259's, etc.
- * 0-7 (char at 536)
- * 8-15 (char at 53a)
- * 16-23 (char at 53c)
- */
-static unsigned long irq_mask = ~0UL;
-#ifdef CONFIG_ALPHA_SABLE
/*
- * Note that the vector reported by the SRM PALcode corresponds to the
- * interrupt mask bits, but we have to manage via more normal IRQs.
- *
- * We have to be able to go back and forth between MASK bits and IRQ:
- * these tables help us do so.
+ * Shadow-copy of masked interrupts.
*/
-static char sable_irq_to_mask[NR_IRQS] = {
- -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
- -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
- 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
-};
-#define IRQ_TO_MASK(irq) (sable_irq_to_mask[(irq)])
-static char sable_mask_to_irq[NR_IRQS] = {
- 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
- 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
- 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
-};
-#else /* CONFIG_ALPHA_SABLE */
-#define IRQ_TO_MASK(irq) (irq)
-#endif /* CONFIG_ALPHA_SABLE */
+unsigned long alpha_irq_mask = ~0UL;
/*
- * Update the hardware with the irq mask passed in MASK. The function
- * exploits the fact that it is known that only bit IRQ has changed.
+ * The ack_irq routine used by 80% of the systems.
*/
-static inline void
-sable_update_hw(unsigned long irq, unsigned long mask)
+void
+generic_ack_irq(unsigned long irq)
{
- /* The "irq" argument is really the mask bit number */
- switch (irq) {
- case 16 ... 23:
- outb(mask >> 16, 0x53d);
- break;
- case 8 ... 15:
- outb(mask >> 8, 0x53b);
- break;
- case 0 ... 7:
- outb(mask, 0x537);
- break;
+ if (irq < 16) {
+ /* Ack the interrupt making it the lowest priority */
+ /* First the slave .. */
+ if (irq > 7) {
+ outb(0xE0 | (irq - 8), 0xa0);
+ irq = 2;
+ }
+ /* .. then the master */
+ outb(0xE0 | irq, 0x20);
}
}
-static inline void
-noritake_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 32 ... 47:
- outw(~(mask >> 32), 0x54c);
- break;
- case 16 ... 31:
- outw(~(mask >> 16), 0x54a);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+/*
+ * Dispatch device interrupts.
+ */
-#ifdef CONFIG_ALPHA_MIATA
-static inline void
-miata_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 47:
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x4000000000000e3bUL;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-#endif
+/* Handle ISA interrupt via the PICs. */
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-static inline void
-alcor_and_xlt_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 47:
- /* On Alcor, at least, lines 20..30 are not connected and can
- generate spurrious interrupts if we turn them on while IRQ
- probing. So explicitly mask them out. */
- mask |= 0x7ff000000000UL;
-
- /* Note inverted sense of mask bits: */
- *(vuip)GRU_INT_MASK = ~(mask >> 16);
- mb();
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+#if defined(CONFIG_ALPHA_GENERIC)
+# define IACK_SC alpha_mv.iack_sc
+#elif defined(CONFIG_ALPHA_APECS)
+# define IACK_SC APECS_IACK_SC
+#elif defined(CONFIG_ALPHA_LCA)
+# define IACK_SC LCA_IACK_SC
+#elif defined(CONFIG_ALPHA_CIA)
+# define IACK_SC CIA_IACK_SC
+#elif defined(CONFIG_ALPHA_PYXIS)
+# define IACK_SC PYXIS_IACK_SC
+#elif defined(CONFIG_ALPHA_TSUNAMI)
+# define IACK_SC TSUNAMI_PCI0_IACK_SC
+#else
+ /* This is bogus but necessary to get it to compile on all platforms. */
+# define IACK_SC 1L
#endif
-static inline void
-mikasa_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 31:
- outw(~(mask >> 16), 0x536); /* note invert */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void
-ruffian_update_hw(unsigned long irq, unsigned long mask)
+void
+isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- switch (irq) {
- case 16 ... 47:
- /* Note inverted sense of mask bits: */
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & 0x00000000ffffffbfUL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
+#if 1
+ /*
+ * Generate a PCI interrupt acknowledge cycle. The PIC will
+ * respond with the interrupt vector of the highest priority
+ * interrupt that is pending. The PALcode sets up the
+ * interrupts vectors such that irq level L generates vector L.
+ */
+ int j = *(vuip) IACK_SC;
+ j &= 0xff;
+ if (j == 7) {
+ if (!(inb(0x20) & 0x80)) {
+ /* It's only a passive release... */
+ return;
+ }
}
-}
-#endif /* RUFFIAN */
-
-#if defined(CONFIG_ALPHA_SX164)
-static inline void
-sx164_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 39:
-#if defined(CONFIG_ALPHA_SRM)
- cserve_update_hw(irq, mask);
+ handle_irq(j, j, regs);
#else
- /* make CERTAIN none of the bogus ints get enabled */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x000000000000003bUL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
-#endif /* SRM */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
+ unsigned long pic;
-}
-#endif /* SX164 */
+ /*
+ * It seems to me that the probability of two or more *device*
+ * interrupts occurring at almost exactly the same time is
+ * pretty low. So why pay the price of checking for
+ * additional interrupts here if the common case can be
+ * handled so much easier?
+ */
+ /*
+ * The first read of gives you *all* interrupting lines.
+ * Therefore, read the mask register and and out those lines
+ * not enabled. Note that some documentation has 21 and a1
+ * write only. This is not true.
+ */
+ pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
+ pic &= ~alpha_irq_mask; /* apply mask */
+ pic &= 0xFFFB; /* mask out cascade & hibits */
-#if defined(CONFIG_ALPHA_DP264)
-static inline void
-dp264_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 63:
- /* make CERTAIN none of the bogus ints get enabled */
- /* HACK ALERT! only CPU#0 is used currently */
- *(vulp)TSUNAMI_CSR_DIM0 =
- ~(mask) & ~0x0000000000000000UL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)TSUNAMI_CSR_DIM0;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
+ while (pic) {
+ int j = ffz(~pic);
+ pic &= pic - 1;
+ handle_irq(j, j, regs);
}
+#endif
}
-#endif /* DP264 */
-#if defined(CONFIG_ALPHA_RAWHIDE)
-static inline void
-rawhide_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 39: /* PCI bus 0 with EISA bridge */
- *(vuip)MCPCIA_INT_MASK0(0) =
- (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
- break;
- case 40 ... 63: /* PCI bus 1 with builtin NCR810 SCSI */
- *(vuip)MCPCIA_INT_MASK0(1) =
- (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-#endif /* RAWHIDE */
+/* Handle interrupts from the SRM, assuming no additional weirdness. */
-/*
- * HW update code for the following platforms:
- *
- * CABRIOLET (AlphaPC64)
- * EB66P
- * EB164
- * PC164
- * LX164
- */
-static inline void
-update_hw_35(unsigned long irq, unsigned long mask)
+void
+srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- switch (irq) {
- case 16 ... 34:
-#if defined(CONFIG_ALPHA_SRM)
- cserve_update_hw(irq, mask);
-#else /* SRM */
- outl(irq_mask >> 16, 0x804);
-#endif /* SRM */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+ int irq, ack;
+ unsigned long flags;
-static inline void
-update_hw_32(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 24 ... 31:
- outb(mask >> 24, 0x27);
- break;
- case 16 ... 23:
- outb(mask >> 16, 0x26);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
-}
-}
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
-static inline void
-update_hw_16(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
-}
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
}
+
/*
- * We manipulate the hardware ourselves.
+ * Initial irq handlers.
*/
-static void update_hw(unsigned long irq, unsigned long mask)
-{
-#if defined(CONFIG_ALPHA_SABLE)
- sable_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_CABRIOLET) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164)
- update_hw_35(irq, mask);
-#elif defined(CONFIG_ALPHA_EB66) || \
- defined(CONFIG_ALPHA_EB64P)
- update_hw_32(irq, mask);
-#elif NR_IRQS == 16
- update_hw_16(irq, mask);
-#else
-#error "How do I update the IRQ hardware?"
-#endif
-}
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction *irq_action[NR_IRQS];
-static inline void mask_irq(unsigned long irq)
+
+static inline void
+mask_irq(unsigned long irq)
{
- irq_mask |= (1UL << irq);
- update_hw(irq, irq_mask);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask |= 1UL << irq, 0);
}
-static inline void unmask_irq(unsigned long irq)
+static inline void
+unmask_irq(unsigned long irq)
{
- irq_mask &= ~(1UL << irq);
- update_hw(irq, irq_mask);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask &= ~(1UL << irq), 1);
}
-void disable_irq(unsigned int irq_nr)
+void
+disable_irq(unsigned int irq_nr)
{
unsigned long flags;
save_and_cli(flags);
- mask_irq(IRQ_TO_MASK(irq_nr));
+ mask_irq(irq_nr);
restore_flags(flags);
}
-void enable_irq(unsigned int irq_nr)
+void
+enable_irq(unsigned int irq_nr)
{
unsigned long flags;
save_and_cli(flags);
- unmask_irq(IRQ_TO_MASK(irq_nr));
+ unmask_irq(irq_nr);
restore_flags(flags);
}
-/*
- * Initial irq handlers.
- */
-static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction *irq_action[NR_IRQS];
-
-int get_irq_list(char *buf)
-{
- int i, len = 0;
- struct irqaction * action;
- int cpu = smp_processor_id();
-
- for (i = 0; i < NR_IRQS; i++) {
- action = irq_action[i];
- if (!action)
- continue;
- len += sprintf(buf+len, "%2d: %10u %c %s",
- i, kstat.irqs[cpu][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;
-}
-
-static inline void ack_irq(int irq)
-{
-#ifdef CONFIG_ALPHA_SABLE
- /* Note that the "irq" here is really the mask bit number */
- switch (irq) {
- case 0 ... 7:
- outb(0xE0 | (irq - 0), 0x536);
- outb(0xE0 | 1, 0x534); /* slave 0 */
- break;
- case 8 ... 15:
- outb(0xE0 | (irq - 8), 0x53a);
- outb(0xE0 | 3, 0x534); /* slave 1 */
- break;
- case 16 ... 24:
- outb(0xE0 | (irq - 16), 0x53c);
- outb(0xE0 | 4, 0x534); /* slave 2 */
- break;
- }
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- if (irq < 16) {
- /* Ack PYXIS ISA interrupt. */
- *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- if (irq > 7) {
- outb(0x20, 0xa0);
- }
- outb(0x20, 0x20);
- } else {
- /* Ack PYXIS PCI interrupt. */
- *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16));
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- }
-#else
- if (irq < 16) {
- /* Ack the interrupt making it the lowest priority */
- /* First the slave .. */
- if (irq > 7) {
- outb(0xE0 | (irq - 8), 0xa0);
- irq = 2;
- }
- /* .. then the master */
- outb(0xE0 | irq, 0x20);
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- /* on ALCOR/XLT, need to dismiss interrupt via GRU */
- *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
- *(vuip)GRU_INT_CLEAR = 0x00000000; mb();
-#endif /* ALCOR || XLT */
- }
-#endif
-}
-
-int check_irq(unsigned int irq)
+int
+check_irq(unsigned int irq)
{
struct irqaction **p;
return -EBUSY;
}
-int request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
+int
+request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
{
int shared = 0;
struct irqaction * action, **p;
unsigned long flags;
- if (irq >= NR_IRQS)
+ if (irq >= ACTUAL_NR_IRQS)
return -EINVAL;
if (IS_RESERVED_IRQ(irq))
return -EINVAL;
if (!handler)
return -EINVAL;
+
p = irq_action + irq;
action = *p;
if (action) {
shared = 1;
}
- if (irq == TIMER_IRQ)
- action = &timer_irq;
- else
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
- GFP_KERNEL);
+ action = &timer_irq;
+ if (irq != TIMER_IRQ) {
+ action = (struct irqaction *)
+ kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ }
if (!action)
return -ENOMEM;
*p = action;
if (!shared)
- unmask_irq(IRQ_TO_MASK(irq));
+ unmask_irq(irq);
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq, void *dev_id)
+void
+free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action, **p;
unsigned long flags;
- if (irq >= NR_IRQS) {
+ if (irq >= ACTUAL_NR_IRQS) {
printk("Trying to free IRQ%d\n",irq);
return;
}
save_and_cli(flags);
*p = action->next;
if (!irq[irq_action])
- mask_irq(IRQ_TO_MASK(irq));
+ mask_irq(irq);
restore_flags(flags);
kfree(action);
return;
printk("Trying to free free IRQ%d\n",irq);
}
-static inline void handle_nmi(struct pt_regs * regs)
+int get_irq_list(char *buf)
{
- printk("Whee.. NMI received. Probable hardware error\n");
- printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
-}
+ int i, len = 0;
+ struct irqaction * action;
+ int cpu = smp_processor_id();
-unsigned int local_irq_count[NR_CPUS];
-unsigned int local_bh_count[NR_CPUS];
+ for (i = 0; i < NR_IRQS; i++) {
+ action = irq_action[i];
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %10u %c %s",
+ i, kstat.irqs[cpu][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;
+}
#ifdef __SMP__
/* Who has global_irq_lock. */
#define INIT_STUCK 100000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; }
+#define STUCK \
+ if (!--stuck) { \
+ printk("wait_on_irq CPU#%d stuck at %08lx, " \
+ "waiting for %08lx (local=%d, global=%d)\n", \
+ cpu, where, previous_irqholder, local_count, \
+ atomic_read(&global_irq_count)); \
+ stuck = INIT_STUCK; \
+ }
-static inline void wait_on_irq(int cpu, unsigned long where)
+static inline void
+wait_on_irq(int cpu, unsigned long where)
{
int stuck = INIT_STUCK;
int local_count = local_irq_count[cpu];
#define INIT_STUCK 10000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
+#define STUCK \
+ if (!--stuck) { \
+ printk("get_irqlock stuck at %08lx, waiting for %08lx\n", \
+ where, previous_irqholder); \
+ stuck = INIT_STUCK; \
+ }
-static inline void get_irqlock(int cpu, unsigned long where)
+static inline void
+get_irqlock(int cpu, unsigned long where)
{
int stuck = INIT_STUCK;
previous_irqholder = where;
}
-void __global_cli(void)
+void
+__global_cli(void)
{
int cpu = smp_processor_id();
unsigned long where;
__cli();
if (!local_irq_count[cpu])
- get_irqlock(smp_processor_id(), where);
+ get_irqlock(smp_processor_id(), where);
}
-void __global_sti(void)
+void
+__global_sti(void)
{
int cpu = smp_processor_id();
if (!local_irq_count[cpu])
- release_irqlock(smp_processor_id());
+ release_irqlock(smp_processor_id());
__sti();
}
#if 0
-unsigned long __global_save_flags(void)
+unsigned long
+__global_save_flags(void)
{
return global_irq_holder == (unsigned char) smp_processor_id();
}
#endif
-void __global_restore_flags(unsigned long flags)
+void
+__global_restore_flags(unsigned long flags)
{
if (flags & 1) {
__global_cli();
#define INIT_STUCK 200000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;}
+#define STUCK \
+ if (!--stuck) { \
+ printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \
+ irq, cpu,global_irq_holder); \
+ stuck = INIT_STUCK; \
+ }
#undef VERBOSE_IRQLOCK_DEBUGGING
-void irq_enter(int cpu, int irq)
+void
+irq_enter(int cpu, int irq)
{
#ifdef VERBOSE_IRQLOCK_DEBUGGING
extern void smp_show_backtrace_all_cpus(void);
int globl_icount = atomic_read(&global_irq_count);
int local_count = local_irq_count[cpu];
- /* It is very important that we load the state variables
- * before we do the first call to printk() as printk()
- * could end up changing them...
- */
+ /* It is very important that we load the state
+ variables before we do the first call to
+ printk() as printk() could end up changing
+ them... */
#if 0
printk("CPU[%d]: BAD! Local IRQ's enabled,"
}
}
-void irq_exit(int cpu, int irq)
+void
+irq_exit(int cpu, int irq)
{
hardirq_exit(cpu);
release_irqlock(cpu);
}
-static void show(char * str)
+static void
+show(char * str)
{
#if 0
int i;
#define MAXCOUNT 100000000
-static inline void wait_on_bh(void)
+static inline void
+wait_on_bh(void)
{
int count = MAXCOUNT;
do {
* Don't wait if we're already running in an interrupt
* context or are inside a bh handler.
*/
-void synchronize_bh(void)
+void
+synchronize_bh(void)
{
if (atomic_read(&global_bh_count)) {
int cpu = smp_processor_id();
}
/* There has to be a better way. */
-void synchronize_irq(void)
+void
+synchronize_irq(void)
{
int cpu = smp_processor_id();
int local_count = local_irq_count[cpu];
}
}
-#else
+#else /* !__SMP__ */
+
#define irq_enter(cpu, irq) (++local_irq_count[cpu])
#define irq_exit(cpu, irq) (--local_irq_count[cpu])
-#endif
-static void unexpected_irq(int irq, struct pt_regs * regs)
+#endif /* __SMP__ */
+
+static void
+unexpected_irq(int irq, struct pt_regs * regs)
{
+#if 0
+#if 1
+ printk("device_interrupt: unexpected interrupt %d\n", irq);
+#else
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++)
+ for (i = 0; i < ACTUAL_NR_IRQS; i++)
if ((action = irq_action[i]))
while (action->handler) {
printk("[%s:%d] ", action->name, i);
action = action->next;
}
printk("\n");
+#endif
+#endif
#if defined(CONFIG_ALPHA_JENSEN)
/* ??? Is all this just debugging, or are the inb's and outb's
#endif
}
-static inline void handle_irq(int irq, struct pt_regs * regs)
+void
+handle_irq(int irq, int ack, struct pt_regs * regs)
{
- struct irqaction * action = irq_action[irq];
+ struct irqaction * action;
int cpu = smp_processor_id();
-
- irq_enter(cpu, irq);
- kstat.irqs[cpu][irq] += 1;
- if (!action) {
- unexpected_irq(irq, regs);
- } else {
- do {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while (action);
- }
- irq_exit(cpu, irq);
-}
-
-static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
-{
- struct irqaction * action;
- int cpu = smp_processor_id();
-
- if ((unsigned) irq > NR_IRQS) {
- printk("device_interrupt: illegal interrupt %d\n", irq);
- return;
- }
+
+ if ((unsigned) irq > ACTUAL_NR_IRQS) {
+ printk("device_interrupt: illegal interrupt %d\n", irq);
+ return;
+ }
irq_enter(cpu, irq);
kstat.irqs[cpu][irq] += 1;
* never unmasked. The autoirq stuff depends on this (it looks
* at the masks before and after doing the probing).
*/
- mask_irq(ack);
- ack_irq(ack);
+ if (ack >= 0) {
+ mask_irq(ack);
+ alpha_mv.ack_irq(ack);
+ }
if (action) {
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- unmask_irq(ack);
+ if (ack >= 0)
+ unmask_irq(ack);
} else {
-#if 1
- printk("device_interrupt: unexpected interrupt %d\n", irq);
-#endif
+ unexpected_irq(irq, regs);
}
irq_exit(cpu, irq);
}
-#ifdef CONFIG_PCI
-
-/*
- * Handle ISA interrupt via the PICs.
- */
-static inline void isa_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
-#if defined(CONFIG_ALPHA_APECS)
-# define IACK_SC APECS_IACK_SC
-#elif defined(CONFIG_ALPHA_LCA)
-# define IACK_SC LCA_IACK_SC
-#elif defined(CONFIG_ALPHA_CIA)
-# define IACK_SC CIA_IACK_SC
-#elif defined(CONFIG_ALPHA_PYXIS)
-# define IACK_SC PYXIS_IACK_SC
-#elif defined(CONFIG_ALPHA_TSUNAMI)
-# define IACK_SC TSUNAMI_PCI0_IACK_SC
-#else
- /*
- * This is bogus but necessary to get it to compile
- * on all platforms. If you try to use this on any
- * other than the intended platforms, you'll notice
- * real fast...
- */
-# define IACK_SC 1L
-#endif
- int j;
-
-#if 1
- /*
- * Generate a PCI interrupt acknowledge cycle. The PIC will
- * respond with the interrupt vector of the highest priority
- * interrupt that is pending. The PALcode sets up the
- * interrupts vectors such that irq level L generates vector L.
- */
- j = *(vuip) IACK_SC;
- j &= 0xff;
- if (j == 7) {
- if (!(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- return;
- }
- }
- device_interrupt(j, j, regs);
-#else
- unsigned long pic;
-
- /*
- * It seems to me that the probability of two or more *device*
- * interrupts occurring at almost exactly the same time is
- * pretty low. So why pay the price of checking for
- * additional interrupts here if the common case can be
- * handled so much easier?
- */
- /*
- * The first read of gives you *all* interrupting lines.
- * Therefore, read the mask register and and out those lines
- * not enabled. Note that some documentation has 21 and a1
- * write only. This is not true.
- */
- pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= ~irq_mask; /* apply mask */
- pic &= 0xFFFB; /* mask out cascade & hibits */
-
- while (pic) {
- j = ffz(~pic);
- pic &= pic - 1;
- device_interrupt(j, j, regs);
- }
-#endif
-}
-
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-/* We have to conditionally compile this because of GRU_xxx symbols */
-static inline void
-alcor_and_xlt_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of the GRU */
- pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
-
-#if 0
- printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8));
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 31) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-#endif /* ALCOR || XLT */
-
-static inline void
-cabriolet_and_eb66p_device_interrupt(unsigned long vector,
- struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* 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.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 4) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-
-static inline void
-mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers */
- pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
- (((unsigned long) inb(0xa0)) << 8) |
- ((unsigned long) inb(0x20));
-
-#if 0
- printk("[0x%08lx]", pld);
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i < 16) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(i, i, regs);
- }
- }
- restore_flags(flags);
-}
-
-static inline void
-eb66_and_eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers */
- pld = inb(0x26) | (inb(0x27) << 8);
- /*
- * Now, for every possible bit set, work through
- * them and call the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
-
- if (i == 5) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-
-#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164)
-/* We have to conditionally compile this because of PYXIS_xxx symbols */
-static inline void
-miata_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
-#if 0
- printk("[0x%08lx/0x%08lx/0x%04x]", pld,
- *(vulp)PYXIS_INT_MASK, inb(0x20) | (inb(0xA0) << 8));
-#endif
-
-#ifdef CONFIG_ALPHA_MIATA
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8)
- * then all the PCI slots/INTXs (12-31).
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x00000000fffff1c4UL;
-#endif
-#ifdef CONFIG_ALPHA_SX164
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7)
- * then all the PCI slots/INTXs (8-23)
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x0000000000ffffc0UL;
-#endif /* SX164 */
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- isa_device_interrupt(vector, regs);
- } else if (i == 6)
- continue;
- else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- tmp = *(vulp)PYXIS_INT_REQ;
- }
- restore_flags(flags);
-}
-#endif /* MIATA || SX164 */
-
-static inline void
-noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers of NORITAKE */
- pld = ((unsigned long) inw(0x54c) << 32) |
- ((unsigned long) inw(0x54a) << 16) |
- ((unsigned long) inb(0xa0) << 8) |
- ((unsigned long) inb(0x20));
-
-#if 0
- printk("[0x%08lx]", pld);
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i < 16) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(i, i, regs);
- }
- }
- restore_flags(flags);
-}
-
-#if defined(CONFIG_ALPHA_DP264)
-/* we have to conditionally compile this because of TSUNAMI_xxx symbols */
-static inline void dp264_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
- unsigned long flags;
-
- __save_and_cli(flags);
-
- /* Read the interrupt summary register of TSUNAMI */
- pld = (*(vulp)TSUNAMI_CSR_DIR0);
-
-#if 0
- printk("[0x%08lx/0x%08lx/0x%04x]", pld,
- *(vulp)TSUNAMI_CSR_DIM0,
- inb(0x20) | (inb(0xA0) << 8));
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 55) {
- isa_device_interrupt(vector, regs);
- } else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
-#if 0
- *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb();
- tmp = *(vulp)TSUNAMI_CSR_DIR0;
-#endif
- }
- __restore_flags(flags);
-}
-#endif /* DP264 */
-
-#if defined(CONFIG_ALPHA_RAWHIDE)
-/* we have to conditionally compile this because of MCPCIA_xxx symbols */
-static inline void rawhide_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
-#if 0
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- __save_and_cli(flags);
-
- /* PLACEHOLDER, perhaps never used if we always do SRM */
-
- __restore_flags(flags);
-#endif
-}
-#endif /* RAWHIDE */
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void
-ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
-
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
- /* For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
- * then all the PCI slots/INTXs (12-31)
- * flash(5) :DWH:
- */
- pld &= 0x00000000ffffff9fUL;/* was ffff7f */
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
-
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- /* Copy this bit from isa_device_interrupt cause
- we need to hook into int 0 for the timer. I
- refuse to soil device_interrupt with ifdefs. */
-
- /* Generate a PCI interrupt acknowledge cycle.
- The PIC will respond with the interrupt
- vector of the highest priority interrupt
- that is pending. The PALcode sets up the
- interrupts vectors such that irq level L
- generates vector L. */
-
- unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
- if (j == 7 && !(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- } else if (j == 0) {
- timer_interrupt(regs);
- ack_irq(0);
- } else {
- device_interrupt(j, j, regs);
- }
- } else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
-
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- *(vulp)PYXIS_INT_REQ; /* read to force the write */
- }
- restore_flags(flags);
-}
-#endif /* RUFFIAN */
-
-static inline void takara_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
- unsigned long flags;
- unsigned intstatus;
-
- save_and_cli(flags);
-
- /*
- * The PALcode will have passed us vectors 0x800 or 0x810,
- * which are fairly arbitrary values and serve only to tell
- * us whether an interrupt has come in on IRQ0 or IRQ1. If
- * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
- * probably ISA, but PCI interrupts can come through IRQ0
- * as well if the interrupt controller isn't in accelerated
- * mode.
- *
- * OTOH, the accelerator thing doesn't seem to be working
- * overly well, so what we'll do instead is try directly
- * examining the Master Interrupt Register to see if it's a
- * PCI interrupt, and if _not_ then we'll pass it on to the
- * ISA handler.
- */
-
- intstatus = inw(0x500) & 15;
- if (intstatus) {
- /*
- * This is a PCI interrupt. Check each bit and
- * despatch an interrupt if it's set.
- */
- if (intstatus & 8) device_interrupt(16+3, 16+3, regs);
- if (intstatus & 4) device_interrupt(16+2, 16+2, regs);
- if (intstatus & 2) device_interrupt(16+1, 16+1, regs);
- if (intstatus & 1) device_interrupt(16+0, 16+0, regs);
- } else
- isa_device_interrupt (vector, regs);
-
- restore_flags(flags);
-}
-
-#endif /* CONFIG_PCI */
-
-/*
- * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
- * 0x9X0 for the local motherboard interrupts..
- *
- * 0x660 - NMI
- *
- * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
- * 0x810 - IRQ1 line printer (duh..)
- * 0x860 - IRQ6 floppy disk
- * 0x8E0 - IRQ14 SCSI controller
- *
- * 0x900 - COM1
- * 0x920 - COM2
- * 0x980 - keyboard
- * 0x990 - mouse
- *
- * PCI-based systems are more sane: they don't have the local
- * interrupts at all, and have only normal PCI interrupts from
- * devices. Happily it's easy enough to do a sane mapping from the
- * Jensen.. Note that this means that we may have to do a hardware
- * "ack" to a different interrupt than we report to the rest of the
- * world.
- */
-static inline void
-srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
-{
- int irq, ack;
- unsigned long flags;
-
- __save_and_cli(flags);
-
-#ifdef __SMP__
-if (smp_processor_id()) printk("srm_device_interrupt on other CPU\n");
-#endif
-
- ack = irq = (vector - 0x800) >> 4;
-
-#ifdef CONFIG_ALPHA_JENSEN
- switch (vector) {
- case 0x660: handle_nmi(regs); return;
- /* local device interrupts: */
- case 0x900: handle_irq(4, regs); return; /* com1 -> irq 4 */
- case 0x920: handle_irq(3, regs); return; /* com2 -> irq 3 */
- case 0x980: handle_irq(1, regs); return; /* kbd -> irq 1 */
- case 0x990: handle_irq(9, regs); return; /* mouse -> irq 9 */
- default:
- if (vector > 0x900) {
- printk("Unknown local interrupt %lx\n", vector);
- }
- }
- /* irq1 is supposed to be the keyboard, silly Jensen
- (is this really needed??) */
- if (irq == 1)
- irq = 7;
-#endif /* CONFIG_ALPHA_JENSEN */
-
-#ifdef CONFIG_ALPHA_MIATA
- /*
- * I really hate to do this, but the MIATA SRM console ignores the
- * low 8 bits in the interrupt summary register, and reports the
- * vector 0x80 *lower* than I expected from the bit numbering in
- * the documentation.
- * This was done because the low 8 summary bits really aren't used
- * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
- * used for this purpose, as PIC interrupts are delivered as the
- * vectors 0x800-0x8f0).
- * But I really don't want to change the fixup code for allocation
- * of IRQs, nor the irq_mask maintenance stuff, both of which look
- * nice and clean now.
- * So, here's this grotty hack... :-(
- */
- if (irq >= 16)
- ack = irq = irq + 8;
-#endif /* CONFIG_ALPHA_MIATA */
-
-#ifdef CONFIG_ALPHA_NORITAKE
- /*
- * I really hate to do this, too, but the NORITAKE SRM console also
- * reports PCI vectors *lower* than I expected from the bit numbers
- * in the documentation.
- * But I really don't want to change the fixup code for allocation
- * of IRQs, nor the irq_mask maintenance stuff, both of which look
- * nice and clean now.
- * So, here's this additional grotty hack... :-(
- */
- if (irq >= 16)
- ack = irq = irq + 1;
-#endif /* CONFIG_ALPHA_NORITAKE */
-
-#ifdef CONFIG_ALPHA_SABLE
- irq = sable_mask_to_irq[(ack)];
-#if 0
- if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
- irq == 14 || irq == 15)
- printk("srm_device_interrupt: vector=0x%lx ack=0x%x"
- " irq=0x%x\n", vector, ack, irq);
-#endif
-#endif /* CONFIG_ALPHA_SABLE */
-
-#ifdef CONFIG_ALPHA_DP264
- /*
- * the DP264 SRM console reports PCI interrupts with a vector
- * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
- * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have
- * it line up with the actual bit numbers from the DIM registers,
- * which is how we manage the interrupts/mask. Sigh...
- */
- if (irq >= 32)
- ack = irq = irq - 16;
-#endif /* DP264 */
-
-#ifdef CONFIG_ALPHA_RAWHIDE
- /*
- * the RAWHIDE SRM console reports PCI interrupts with a vector
- * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
- * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
- * it line up with the actual bit numbers from the REQ registers,
- * which is how we manage the interrupts/mask. Sigh...
- *
- * also, PCI #1 interrupts are offset some more... :-(
- */
- if (irq == 52)
- ack = irq = 56; /* SCSI on PCI 1 is special */
- else {
- if (irq >= 24) /* adjust all PCI interrupts down 8 */
- ack = irq = irq - 8;
- if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */
- ack = irq = irq - 8;
- }
-#endif /* RAWHIDE */
-
- device_interrupt(irq, ack, regs);
-
- __restore_flags(flags);
-}
/*
* Start listening for interrupts..
*/
-unsigned long probe_irq_on(void)
+
+unsigned long
+probe_irq_on(void)
{
struct irqaction * action;
unsigned long irqs = 0;
unsigned long delay;
unsigned int i;
- for (i = NR_IRQS - 1; i > 0; i--) {
+ for (i = ACTUAL_NR_IRQS - 1; i > 0; i--) {
if (!(PROBE_MASK & (1UL << i))) {
continue;
}
for (delay = jiffies + HZ/10; delay > jiffies; )
barrier();
- /* now filter out any obviously spurious interrupts */
- return irqs & ~irq_mask;
+ /* Now filter out any obviously spurious interrupts. */
+ return irqs & ~alpha_irq_mask;
}
/*
* we have several candidates (but we return the lowest-numbered
* one).
*/
-int probe_irq_off(unsigned long irqs)
+
+int
+probe_irq_off(unsigned long irqs)
{
int i;
- irqs &= irq_mask;
+ irqs &= alpha_irq_mask;
if (!irqs)
return 0;
i = ffz(~irqs);
return i;
}
-extern void lca_machine_check (unsigned long vector, unsigned long la,
- struct pt_regs *regs);
-extern void apecs_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void cia_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void pyxis_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void t2_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void tsunami_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void mcpcia_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-
-static void
-machine_check(unsigned long vector, unsigned long la, struct pt_regs *regs)
-{
-#if defined(CONFIG_ALPHA_LCA)
- lca_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_APECS)
- apecs_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_CIA)
- cia_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_PYXIS)
- pyxis_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_T2)
- t2_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_TSUNAMI)
- tsunami_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_MCPCIA)
- mcpcia_machine_check(vector, la, regs);
-#else
- printk("Machine check\n");
-#endif
-}
+
+/*
+ * The main interrupt entry point.
+ */
asmlinkage void
do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
switch (type) {
case 0:
#ifdef __SMP__
-/* irq_enter(smp_processor_id(), 0); ??????? */
handle_ipi(®s);
-/* irq_exit(smp_processor_id(), 0); ??????? */
return;
-#else /* __SMP__ */
+#else
printk("Interprocessor interrupt? You must be kidding\n");
-#endif /* __SMP__ */
+#endif
break;
case 1:
- handle_irq(RTC_IRQ, ®s);
+ handle_irq(RTC_IRQ, -1, ®s);
return;
case 2:
- machine_check(vector, la_ptr, ®s);
+ alpha_mv.machine_check(vector, la_ptr, ®s);
return;
case 3:
-#if defined(CONFIG_ALPHA_JENSEN) || \
- defined(CONFIG_ALPHA_NONAME) || \
- defined(CONFIG_ALPHA_P2K) || \
- defined(CONFIG_ALPHA_SRM)
- srm_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_MIATA) || \
- defined(CONFIG_ALPHA_SX164)
- miata_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_ALCOR) || \
- defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_CABRIOLET) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164)
- cabriolet_and_eb66p_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_EB66) || \
- defined(CONFIG_ALPHA_EB64P)
- eb66_and_eb64p_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_device_interrupt(vector, ®s);
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_device_interrupt(vector, ®s);
-#elif NR_IRQS == 16
- isa_device_interrupt(vector, ®s);
-#endif
+ alpha_mv.device_interrupt(vector, ®s);
return;
case 4:
printk("Performance counter interrupt\n");
printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
}
-extern asmlinkage void entInt(void);
-
-static inline void sable_init_IRQ(void)
-{
- outb(irq_mask , 0x537); /* slave 0 */
- outb(irq_mask >> 8, 0x53b); /* slave 1 */
- outb(irq_mask >> 16, 0x53d); /* slave 2 */
- outb(0x44, 0x535); /* enable cascades in master */
-}
-
-#if defined(CONFIG_ALPHA_SX164)
-static inline void sx164_init_IRQ(void)
-{
-#if !defined(CONFIG_ALPHA_SRM)
- /* note invert on MASK bits */
- *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb();
- *(vulp)PYXIS_INT_MASK;
-#endif /* !SRM */
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif /* SX164 */
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void ruffian_init_IRQ(void)
-{
- /* invert 6&7 for i82371 */
- *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
- *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
- *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
- *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
-
- outb(0x11,0xA0);
- outb(0x08,0xA1);
- outb(0x02,0xA1);
- outb(0x01,0xA1);
- outb(0xFF,0xA1);
-
- outb(0x11,0x20);
- outb(0x00,0x21);
- outb(0x04,0x21);
- outb(0x01,0x21);
- outb(0xFF,0x21);
-
- /* Send -INTA pulses to clear any pending interrupts ...*/
- *(vuip) IACK_SC;
-
- /* Finish writing the 82C59A PIC Operation Control Words */
- outb(0x20,0xA0);
- outb(0x20,0x20);
-
- /* Turn on the interrupt controller, the timer interrupt */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(0); /* enable timer */
- enable_irq(2); /* enable 2nd PIC cascade */
-}
-#endif /* RUFFIAN */
-
-#ifdef CONFIG_ALPHA_MIATA
-static inline void miata_init_IRQ(void)
-{
- /* note invert on MASK bits */
- *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb(); /* invert */
-#if 0
- /* these break on MiataGL so we'll try not to do it at all */
- *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
- *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
-#endif
- /* clear upper timer */
- *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb();
-
- enable_irq(16 + 2); /* enable HALT switch - SRM only? */
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif
-
-static inline void noritake_init_IRQ(void)
-{
- outw(~(irq_mask >> 16), 0x54a); /* note invert */
- outw(~(irq_mask >> 32), 0x54c); /* note invert */
- enable_irq(2); /* enable cascade */
-}
-
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-static inline void alcor_and_xlt_init_IRQ(void)
-{
- *(vuip)GRU_INT_MASK = ~(irq_mask >> 16); mb(); /* note invert */
- *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */
- *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
- *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */
-
- enable_irq(16 + 31); /* enable (E)ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif /* ALCOR || XLT */
-
-static inline void mikasa_init_IRQ(void)
-{
- outw(~(irq_mask >> 16), 0x536); /* note invert */
- enable_irq(2); /* enable cascade */
-}
-
-#if defined(CONFIG_ALPHA_DP264)
-static inline void dp264_init_IRQ(void)
-{
- /* note invert on MASK bits */
- *(vulp)TSUNAMI_CSR_DIM0 =
- ~(irq_mask) & ~0x0000000000000000UL; mb();
- *(vulp)TSUNAMI_CSR_DIM0;
- enable_irq(55); /* enable CYPRESS interrupt controller (ISA) */
- enable_irq(2);
-}
-#endif /* DP264 */
-
-#if defined(CONFIG_ALPHA_RAWHIDE)
-static inline void rawhide_init_IRQ(void)
-{
- /* HACK ALERT! only PCI busses 0 and 1 are used currently,
- and routing is only to CPU #1*/
-
- *(vuip)MCPCIA_INT_MASK0(0) =
- (~((irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
-
- *(vuip)MCPCIA_INT_MASK0(1) =
- (~((irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
- enable_irq(2);
-}
-#endif /* RAWHIDE */
-
-static inline void takara_init_IRQ(void)
-{
- unsigned int ctlreg = inl(0x500);
-
- ctlreg &= ~0x8000; /* return to non-accelerated mode */
- outw(ctlreg >> 16, 0x502);
- outw(ctlreg & 0xFFFF, 0x500);
- ctlreg = 0x05107c00; /* enable the PCI interrupt register */
- printk("Setting to 0x%08x\n", ctlreg);
- outw(ctlreg >> 16, 0x502);
- outw(ctlreg & 0xFFFF, 0x500);
- enable_irq(2);
-}
-
-static inline void init_IRQ_35(void)
-{
-#if !defined(CONFIG_ALPHA_SRM)
- outl(irq_mask >> 16, 0x804);
-#endif /* !SRM */
- enable_irq(16 + 4); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
-}
-
-static inline void init_IRQ_32(void)
-{
- outb(irq_mask >> 16, 0x26);
- outb(irq_mask >> 24, 0x27);
- enable_irq(16 + 5); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
-}
-
-static inline void init_IRQ_16(void)
-{
- enable_irq(2); /* enable cascade */
-}
-
void __init
init_IRQ(void)
{
wrent(entInt, 0);
-
-/* FIXME FIXME FIXME FIXME FIXME */
-#if !defined(CONFIG_ALPHA_DP264)
- /* we need to figure out why these fail on the DP264 */
- outb(0, DMA1_RESET_REG);
- outb(0, DMA2_RESET_REG);
-#endif /* !DP264 */
-/* FIXME FIXME FIXME FIXME FIXME */
-#if !defined(CONFIG_ALPHA_SX164) && !defined(CONFIG_ALPHA_DP264)
- outb(0, DMA1_CLR_MASK_REG);
- /* we need to figure out why this fails on the SX164 */
- outb(0, DMA2_CLR_MASK_REG);
-#endif /* !SX164 && !DP264 */
-/* end FIXMEs */
-
-#if defined(CONFIG_ALPHA_SABLE)
- sable_init_IRQ();
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_init_IRQ();
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_init_IRQ();
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_init_IRQ();
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_init_IRQ();
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_init_IRQ();
-#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) || \
- defined(CONFIG_ALPHA_EB164)
- init_IRQ_35();
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_init_IRQ();
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_init_IRQ();
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_init_IRQ();
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_init_IRQ();
-#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
- init_IRQ_32();
-#elif NR_IRQS == 16
- init_IRQ_16();
-#else
-#error "How do I initialize the interrupt hardware?"
-#endif
+ alpha_mv.init_irq();
}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/irq.h
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the IRQ handling routines in irq.c.
+ */
+
+
+/* FIXME FIXME FIXME FIXME FIXME */
+/* We need to figure out why these fail on the DP264 & SX164. Otherwise
+ we'd just do this in init_IRQ(). */
+#define STANDARD_INIT_IRQ_PROLOG \
+ outb(0, DMA1_RESET_REG); \
+ outb(0, DMA2_RESET_REG); \
+ outb(0, DMA1_CLR_MASK_REG); \
+ outb(0, DMA2_CLR_MASK_REG)
+
+extern unsigned long alpha_irq_mask;
+
+extern void generic_ack_irq(unsigned long irq);
+extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
+extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
+
+extern void handle_irq(int irq, int ack, struct pt_regs * regs);
+++ /dev/null
-/*
- * Code common to all LCA chips.
- *
- * Written by David Mosberger (davidm@cs.arizona.edu) with some code
- * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
- * bios code.
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
-/*
- * Machine check reasons. Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_UNKNOWN 0x008A
-#define MCHK_K_CACKSOFT 0x008C
-#define MCHK_K_BUGCHECK 0x008E
-#define MCHK_K_OS_BUGCHECK 0x0090
-#define MCHK_K_DCPERR 0x0092
-#define MCHK_K_ICPERR 0x0094
-
-/*
- * Platform-specific machine-check reasons:
- */
-#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */
-#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
-#define MCHK_K_DCSR 0x208 /* all but Noname */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
-unsigned int LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the LCA_IOC_CONF 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | | | | | | | | | | | | | | |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 long addr;
-
- if (bus == 0) {
- int device = device_fn >> 3;
- int func = device_fn & 0x7;
-
- /* type 0 configuration cycle: */
-
- if (device > 12) {
- return -1;
- }
-
- *(vulp)LCA_IOC_CONF = 0;
- addr = (1 << (11 + device)) | (func << 8) | where;
- } else {
- /* type 1 configuration cycle: */
- *(vulp)LCA_IOC_CONF = 1;
- addr = (bus << 16) | (device_fn << 8) | where;
- }
- *pci_addr = addr;
- return 0;
-}
-
-
-static unsigned int conf_read(unsigned long addr)
-{
- unsigned long flags, code, stat0;
- unsigned int value;
-
- save_flags(flags);
- cli();
-
- /* reset status register to avoid loosing errors: */
- stat0 = *(vulp)LCA_IOC_STAT0;
- *(vulp)LCA_IOC_STAT0 = stat0;
- mb();
-
- /* access configuration space: */
-
- value = *(vuip)addr;
- draina();
-
- stat0 = *(vulp)LCA_IOC_STAT0;
- if (stat0 & LCA_IOC_STAT0_ERR) {
- code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
- & LCA_IOC_STAT0_CODE_MASK);
- if (code != 1) {
- printk("lca.c:conf_read: got stat0=%lx\n", stat0);
- }
-
- /* reset error status: */
- *(vulp)LCA_IOC_STAT0 = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
-
- value = 0xffffffff;
- }
- restore_flags(flags);
- return value;
-}
-
-
-static void conf_write(unsigned long addr, unsigned int value)
-{
- unsigned long flags, code, stat0;
-
- save_flags(flags); /* avoid getting hit by machine check */
- cli();
-
- /* reset status register to avoid loosing errors: */
- stat0 = *(vulp)LCA_IOC_STAT0;
- *(vulp)LCA_IOC_STAT0 = stat0;
- mb();
-
- /* access configuration space: */
-
- *(vuip)addr = value;
- draina();
-
- stat0 = *(vulp)LCA_IOC_STAT0;
- if (stat0 & LCA_IOC_STAT0_ERR) {
- code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
- & LCA_IOC_STAT0_CODE_MASK);
- if (code != 1) {
- printk("lca.c:conf_write: got stat0=%lx\n", stat0);
- }
-
- /* reset error status: */
- *(vulp)LCA_IOC_STAT0 = stat0;
- mb();
- wrmces(0x7); /* reset machine check */
- }
- restore_flags(flags);
-}
-
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x00;
- *value = conf_read(addr) >> ((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 = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x08;
- *value = conf_read(addr) >> ((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 = LCA_CONF;
- unsigned long pci_addr;
-
- *value = 0xffffffff;
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- *value = conf_read(addr);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x00;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr = LCA_CONF;
- unsigned long pci_addr;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8));
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
-{
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33)) &&
- (*(vulp)LCA_IOC_T_BASE0 == 0))
- {
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
-#if 1
- printk("lca_init: using Window 0 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE0,
- *(vulp)LCA_IOC_W_MASK0,
- *(vulp)LCA_IOC_T_BASE0);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33)) &&
- (*(vulp)LCA_IOC_T_BASE1 == 0))
- {
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
-#if 1
- printk("lca_init: using Window 1 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE1,
- *(vulp)LCA_IOC_W_MASK1,
- *(vulp)LCA_IOC_T_BASE1);
-#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 1 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
- *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
-
- *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
- *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
- *(vulp)LCA_IOC_T_BASE0 = 0;
- }
-
- /*
- * Disable PCI parity for now. The NCR53c810 chip has
- * troubles meeting the PCI spec which results in
- * data parity errors.
- */
- *(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
- return mem_start;
-}
-
-
-/*
- * Constants used during machine-check handling. I suppose these
- * could be moved into lca.h but I don't see much reason why anybody
- * else would want to use them.
- */
-
-#define ESR_EAV (1UL<< 0) /* error address valid */
-#define ESR_CEE (1UL<< 1) /* correctable error */
-#define ESR_UEE (1UL<< 2) /* uncorrectable error */
-#define ESR_WRE (1UL<< 3) /* write-error */
-#define ESR_SOR (1UL<< 4) /* error source */
-#define ESR_CTE (1UL<< 7) /* cache-tag error */
-#define ESR_MSE (1UL<< 9) /* multiple soft errors */
-#define ESR_MHE (1UL<<10) /* multiple hard errors */
-#define ESR_NXM (1UL<<12) /* non-existent memory */
-
-#define IOC_ERR ( 1<<4) /* ioc logs an error */
-#define IOC_CMD_SHIFT 0
-#define IOC_CMD (0xf<<IOC_CMD_SHIFT)
-#define IOC_CODE_SHIFT 8
-#define IOC_CODE (0xf<<IOC_CODE_SHIFT)
-#define IOC_LOST ( 1<<5)
-#define IOC_P_NBR ((__u32) ~((1<<13) - 1))
-
-
-void mem_error (unsigned long esr, unsigned long ear)
-{
- printk(" %s %s error to %s occurred at address %x\n",
- *((esr & ESR_CEE) ? "Correctable" :
- (esr & ESR_UEE) ? "Uncorrectable" : "A"),
- (esr & ESR_WRE) ? "write" : "read",
- (esr & ESR_SOR) ? "memory" : "b-cache",
- (unsigned) (ear & 0x1ffffff8));
- if (esr & ESR_CTE) {
- printk(" A b-cache tag parity error was detected.\n");
- }
- if (esr & ESR_MSE) {
- printk(" Several other correctable errors occurred.\n");
- }
- if (esr & ESR_MHE) {
- printk(" Several other uncorrectable errors occurred.\n");
- }
- if (esr & ESR_NXM) {
- printk(" Attempted to access non-existent memory.\n");
- }
-}
-
-
-void ioc_error (__u32 stat0, __u32 stat1)
-{
- static const char * const pci_cmd[] = {
- "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
- "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3",
- "Rsvd4", "Configuration Read", "Configuration Write",
- "Memory Read Multiple", "Dual Address", "Memory Read Line",
- "Memory Write and Invalidate"
- };
- static const char * const err_name[] = {
- "exceeded retry limit", "no device", "bad data parity",
- "target abort", "bad address parity", "page table read error",
- "invalid page", "data error"
- };
- unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
- unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT;
-
- printk(" %s initiated PCI %s cycle to address %x"
- " failed due to %s.\n",
- code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
-
- if (code == 5 || code == 6) {
- printk(" (Error occurred at PCI memory address %x.)\n",
- (stat0 & ~IOC_P_NBR));
- }
- if (stat0 & IOC_LOST) {
- printk(" Other PCI errors occurred simultaneously.\n");
- }
-}
-
-
-void lca_machine_check (unsigned long vector, unsigned long la,
- struct pt_regs *regs)
-{
- unsigned long * ptr;
- const char * reason;
- union el_lca el;
- char buf[128];
- long i;
-
- printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
- la, regs->pc);
- el.c = (struct el_common *) la;
- /*
- * The first quadword after the common header always seems to
- * be the machine check reason---don't know why this isn't
- * part of the common header instead. In the case of a long
- * logout frame, the upper 32 bits is the machine check
- * revision level, which we ignore for now.
- */
- switch (el.c->code & 0xffffffff) {
- case MCHK_K_TPERR: reason = "tag parity error"; break;
- case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "access to non-existent memory"; break;
- case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
- case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
- case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
- case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
- case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
- case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
- case MCHK_K_ICPERR: reason = "i-cache parity error"; break;
- case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break;
- case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
- case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
- case MCHK_K_UNKNOWN:
- default:
- sprintf(buf, "reason for machine-check unknown (0x%lx)",
- el.c->code & 0xffffffff);
- reason = buf;
- break;
- }
-
- wrmces(rdmces()); /* reset machine check pending flag */
-
- switch (el.c->size) {
- case sizeof(struct el_lca_mcheck_short):
- printk(KERN_CRIT
- " Reason: %s (short frame%s, dc_stat=%lx):\n",
- reason, el.c->retry ? ", retryable" : "",
- el.s->dc_stat);
- if (el.s->esr & ESR_EAV) {
- mem_error(el.s->esr, el.s->ear);
- }
- if (el.s->ioc_stat0 & IOC_ERR) {
- ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
- }
- break;
-
- case sizeof(struct el_lca_mcheck_long):
- printk(KERN_CRIT " Reason: %s (long frame%s):\n",
- reason, el.c->retry ? ", retryable" : "");
- printk(KERN_CRIT
- " reason: %lx exc_addr: %lx dc_stat: %lx\n",
- el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
- printk(KERN_CRIT " car: %lx\n", el.l->car);
- if (el.l->esr & ESR_EAV) {
- mem_error(el.l->esr, el.l->ear);
- }
- if (el.l->ioc_stat0 & IOC_ERR) {
- ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
- }
- break;
-
- default:
- printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size);
- }
-
- /* dump the logout area to give all info: */
-
- ptr = (unsigned long *) la;
- for (i = 0; i < el.c->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-}
-
-/*
- * The following routines are needed to support the SPEED changing
- * necessary to successfully manage the thermal problem on the AlphaBook1.
- */
-
-void
-lca_clock_print(void)
-{
- long pmr_reg;
-
- pmr_reg = READ_PMR;
-
- printk("Status of clock control:\n");
- printk("\tPrimary clock divisor\t0x%x\n", GET_PRIMARY(pmr_reg));
- printk("\tOverride clock divisor\t0x%x\n", GET_OVERRIDE(pmr_reg));
- printk("\tInterrupt override is %s\n",
- (pmr_reg & LCA_PMR_INTO) ? "on" : "off");
- printk("\tDMA override is %s\n",
- (pmr_reg & LCA_PMR_DMAO) ? "on" : "off");
-
-}
-
-int
-lca_get_clock(void)
-{
- long pmr_reg;
-
- pmr_reg = READ_PMR;
- return(GET_PRIMARY(pmr_reg));
-
-}
-
-void
-lca_clock_fiddle(int divisor)
-{
- long pmr_reg;
-
- pmr_reg = READ_PMR;
- SET_PRIMARY_CLOCK(pmr_reg, divisor);
- /* lca_norm_clock = divisor; */
- WRITE_PMR(pmr_reg);
- mb();
-}
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/machvec.h
+ *
+ * Copyright (C) 1997, 1998 Richard Henderson
+ *
+ * This file has goodies to help simplify instantiation of machine vectors.
+ */
+
+
+/* Whee. TSUNAMI doesn't have an HAE. Fix things up for the GENERIC
+ kernel by defining the HAE address to be that of the cache. Now
+ we can read and write it as we like. ;-) */
+#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
+
+/* Only a few systems don't define IACK_SC, handling all interrupts through
+ the SRM console. But splitting out that one case from IO() below
+ seems like such a pain. Define this to get things to compile. */
+#define JENSEN_IACK_SC 1
+#define T2_IACK_SC 1
+
+
+/*
+ * Some helpful macros for filling in the blanks.
+ */
+
+#define CAT1(x,y) x##y
+#define CAT(x,y) CAT1(x,y)
+
+#define DO_DEFAULT_RTC \
+ rtc_port: 0x70, rtc_addr: 0x80
+
+#define DO_EV4_MMU \
+ max_asn: EV4_MAX_ASN, \
+ mmu_context_mask: ~0UL, \
+ mv_get_mmu_context: ev4_get_mmu_context, \
+ mv_flush_tlb_current: ev4_flush_tlb_current, \
+ mv_flush_tlb_other: ev4_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev4_flush_tlb_current_page
+
+#define DO_EV5_MMU \
+ max_asn: EV5_MAX_ASN, \
+ mmu_context_mask: ~0UL, \
+ mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_flush_tlb_current: ev5_flush_tlb_current, \
+ mv_flush_tlb_other: ev5_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev5_flush_tlb_current_page
+
+#define DO_EV6_MMU \
+ max_asn: EV5_MAX_ASN, \
+ mmu_context_mask: 0xfffffffffful, \
+ mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_flush_tlb_current: ev5_flush_tlb_current, \
+ mv_flush_tlb_other: ev5_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev5_flush_tlb_current_page
+
+#define IO_LITE(UP,low1,low2) \
+ hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \
+ iack_sc: CAT(UP,_IACK_SC), \
+ mv_inb: CAT(low1,_inb), \
+ mv_inw: CAT(low1,_inw), \
+ mv_inl: CAT(low1,_inl), \
+ mv_outb: CAT(low1,_outb), \
+ mv_outw: CAT(low1,_outw), \
+ mv_outl: CAT(low1,_outl), \
+ mv_readb: CAT(low1,_readb), \
+ mv_readw: CAT(low1,_readw), \
+ mv_readl: CAT(low1,_readl), \
+ mv_readq: CAT(low1,_readq), \
+ mv_writeb: CAT(low1,_writeb), \
+ mv_writew: CAT(low1,_writew), \
+ mv_writel: CAT(low1,_writel), \
+ mv_writeq: CAT(low1,_writeq), \
+ mv_dense_mem: CAT(low2,_dense_mem)
+
+#define IO(UP,low1,low2) \
+ IO_LITE(UP,low1,low2), \
+ pci_read_config_byte: CAT(low2,_pcibios_read_config_byte), \
+ pci_read_config_word: CAT(low2,_pcibios_read_config_word), \
+ pci_read_config_dword: CAT(low2,_pcibios_read_config_dword), \
+ pci_write_config_byte: CAT(low2,_pcibios_write_config_byte), \
+ pci_write_config_word: CAT(low2,_pcibios_write_config_word), \
+ pci_write_config_dword: CAT(low2,_pcibios_write_config_dword), \
+ dma_win_base: CAT(UP,_DMA_WIN_BASE_DEFAULT), \
+ dma_win_size: CAT(UP,_DMA_WIN_SIZE_DEFAULT)
+
+/* Any assembler that can generate a GENERIC kernel can generate BWX
+ instructions. So always use them for PYXIS I/O. */
+
+#define DO_APECS_IO IO(APECS,apecs,apecs)
+#define DO_CIA_IO IO(CIA,cia,cia)
+#define DO_LCA_IO IO(LCA,lca,lca)
+#define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia)
+#define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis)
+#define DO_T2_IO IO(T2,t2,t2)
+#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami)
+
+#define BUS(which) \
+ mv_virt_to_bus: CAT(which,_virt_to_bus), \
+ mv_bus_to_virt: CAT(which,_bus_to_virt)
+
+#define DO_APECS_BUS BUS(apecs)
+#define DO_CIA_BUS BUS(cia)
+#define DO_LCA_BUS BUS(lca)
+#define DO_MCPCIA_BUS BUS(mcpcia)
+#define DO_PYXIS_BUS BUS(pyxis)
+#define DO_T2_BUS BUS(t2)
+#define DO_TSUNAMI_BUS BUS(tsunami)
+
+
+/*
+ * In a GENERIC kernel, we have lots of these vectors floating about,
+ * all but one of which we want to go away. In a non-GENERIC kernel,
+ * we want only one, ever.
+ *
+ * Accomplish this in the GENERIC kernel by puting all of the vectors
+ * in the .init.data section where they'll go away. We'll copy the
+ * one we want to the real alpha_mv vector in setup_arch.
+ *
+ * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
+ * one of the vectors, which will not reside in .init.data. We then
+ * alias this one vector to alpha_mv, so no copy is needed.
+ *
+ * Upshot: set __initdata to nothing for non-GENERIC kernels.
+ */
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define __initmv __initdata
+#define ALIAS_MV(x)
+#else
+#define __initmv
+
+/* GCC actually has a syntax for defining aliases, but is under some
+ delusion that you shouldn't be able to declare it extern somewhere
+ else beforehand. Fine. We'll do it ourselves. */
+#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv");
+#endif
+++ /dev/null
-/*
- * Code common to all MCbus-PCI adaptor chipsets
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef CONFIG_ALPHA_MCPCIA
-
-#undef DEBUG_CFG
-
-#ifdef DEBUG_CFG
-# define DBG_CFG(args) printk args
-#else
-# define DBG_CFG(args)
-#endif
-
-#undef DEBUG_PCI
-
-#ifdef DEBUG_PCI
-# define DBG_PCI(args) printk args
-#else
-# define DBG_PCI(args)
-#endif
-
-#define DEBUG_MCHECK
-
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-# define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
-static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
-static unsigned int MCPCIA_jd[NR_CPUS];
-
-#define MCPCIA_MAX_HOSES 2
-static int mcpcia_num_hoses = 0;
-
-static int pci_probe_enabled = 0; /* disable to start */
-
-static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose;
-
-struct linux_hose_info *bus2hose[256];
-
-static inline unsigned long long_align(unsigned long addr)
-{
- return ((addr + (sizeof(unsigned long) - 1)) &
- ~(sizeof(unsigned long) - 1));
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
-unsigned int MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
-unsigned long mcpcia_sm_base_r1, mcpcia_sm_base_r2, mcpcia_sm_base_r3;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the MCPCIA_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 unsigned int
-conf_read(unsigned long addr, unsigned char type1,
- struct linux_hose_info *hose)
-{
- unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
- unsigned int stat0, value, temp, cpu;
-
- cpu = smp_processor_id();
-
- save_and_cli(flags);
-
- DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
- addr, type1, hoseno));
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
-
- mb();
- draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- MCPCIA_mcheck_taken[cpu] = 0;
- mb();
- /* access configuration space: */
- value = *((vuip)addr);
- mb();
- mb(); /* magic */
- if (MCPCIA_mcheck_taken[cpu]) {
- MCPCIA_mcheck_taken[cpu] = 0;
- value = 0xffffffffU;
- mb();
- }
- MCPCIA_mcheck_expected[cpu] = 0;
- mb();
-
- DBG_CFG(("conf_read(): finished\n"));
-
- restore_flags(flags);
- return value;
-}
-
-
-static void
-conf_write(unsigned long addr, unsigned int value, unsigned char type1,
- struct linux_hose_info *hose)
-{
- unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
- unsigned int stat0, temp, cpu;
-
- cpu = smp_processor_id();
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
-
- draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- mb();
- /* access configuration space: */
- *((vuip)addr) = value;
- mb();
- mb(); /* magic */
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
- MCPCIA_mcheck_expected[cpu] = 0;
- mb();
-
- DBG_CFG(("conf_write(): finished\n"));
- restore_flags(flags);
-}
-
-static int mk_conf_addr(struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
-{
- unsigned long addr;
-
- if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */
- return -1;
-
- DBG_CFG(("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));
-
- /* type 1 configuration cycle for *ALL* busses */
- *type1 = 1;
-
- if (hose->pci_first_busno == bus)
- bus = 0;
- addr = (bus << 16) | (device_fn << 8) | (where);
- addr <<= 5; /* swizzle for SPARSE */
- addr |= hose->pci_config_space;
-
- *pci_addr = addr;
- DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
- return 0;
-}
-
-
-int hose_read_config_byte (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xff;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x00; /* or in length */
-
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_read_config_word (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x08; /* or in length */
-
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_read_config_dword (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xffffffff;
-
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= 0x18; /* or in length */
-
- *value = conf_read(addr, type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_byte (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x00; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_word (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x08; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_dword (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x18; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value)
-{
- return hose_read_config_byte(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value)
-{
- return hose_read_config_word(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value)
-{
- return hose_read_config_dword(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value)
-{
- return hose_write_config_byte(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value)
-{
- return hose_write_config_word(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value)
-{
- return hose_write_config_dword(bus2hose[bus], bus, devfn, where, value);
-}
-
-unsigned long mcpcia_init(unsigned long mem_start, unsigned long mem_end)
-{
- struct linux_hose_info *hose;
- unsigned int mcpcia_err;
- unsigned int pci_rev;
- int h;
-
- mem_start = long_align(mem_start);
-
- for (h = 0; h < NR_CPUS; h++) {
- MCPCIA_mcheck_expected[h] = 0;
- MCPCIA_mcheck_taken[h] = 0;
- }
-
- /* first, find how many hoses we have */
- for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
- pci_rev = *(vuip)MCPCIA_REV(h);
-#if 0
- printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n",
- pci_rev, h);
-#endif
- if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
- mcpcia_num_hoses++;
-
- hose = (struct linux_hose_info *)mem_start;
- mem_start = long_align(mem_start + sizeof(*hose));
-
- memset(hose, 0, sizeof(*hose));
-
- if (mcpcia_root)
- mcpcia_last_hose->next = hose;
- else
- mcpcia_root = hose;
- mcpcia_last_hose = hose;
-
- hose->pci_io_space = MCPCIA_IO(h);
- hose->pci_mem_space = MCPCIA_DENSE(h);
- hose->pci_config_space = MCPCIA_CONF(h);
- hose->pci_sparse_space = MCPCIA_SPARSE(h);
- hose->pci_hose_index = h;
- hose->pci_first_busno = 255;
- hose->pci_last_busno = 0;
- }
- }
-
-#if 1
- printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses);
-#endif
-
- /* now do init for each hose */
- for (hose = mcpcia_root; hose; hose = hose->next) {
- h = hose->pci_hose_index;
-#if 0
-#define PRINTK printk
-PRINTK("mcpcia_init: -------- hose %d --------\n",h);
-PRINTK("mcpcia_init: MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
-PRINTK("mcpcia_init: MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
-PRINTK("mcpcia_init: MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
-PRINTK("mcpcia_init: MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
-PRINTK("mcpcia_init: MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
-PRINTK("mcpcia_init: MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
-PRINTK("mcpcia_init: MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
-PRINTK("mcpcia_init: MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
-PRINTK("mcpcia_init: MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
-PRINTK("mcpcia_init: MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
-#endif
-
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
-#if 0
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
- mcpcia_err &= ~4;
- *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
- mb();
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
-#endif
-
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
- mcpcia_err |= 0x0006; /* master/target abort */
- *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
- mb() ;
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T0_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 0 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W0_BASE(h),
- *(vuip)MCPCIA_W0_MASK(h),
- *(vuip)MCPCIA_T0_BASE(h));
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T1_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U))
-{
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 1 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W1_BASE(h),
- *(vuip)MCPCIA_W1_MASK(h),
- *(vuip)MCPCIA_T1_BASE(h));
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T2_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 2 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W2_BASE(h),
- *(vuip)MCPCIA_W2_MASK(h),
- *(vuip)MCPCIA_T2_BASE(h));
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T3_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 3 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W3_BASE(h),
- *(vuip)MCPCIA_W3_MASK(h),
- *(vuip)MCPCIA_T3_BASE(h));
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * 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)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)MCPCIA_T0_BASE(h) = 0;
-
- *(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
-
- *(vuip)MCPCIA_HBASE(h) = 0x0 ;
- mb();
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("mcpcia_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
-#if 0
- {
- unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
- printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl);
- *(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
- mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
- }
-#endif
-
- {
- unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
- unsigned int mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h);
-#if 0
- printk("mcpcia_init: HAE_MEM was 0x%x\n", mcpcia_hae_mem);
- printk("mcpcia_init: HAE_IO was 0x%x\n", mcpcia_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- sigh... For the SRM setup, unless we know apriori what the HAE
- contents will be, we need to setup the arbitrary region bases
- so we can test against the range of addresses and tailor the
- region chosen for the SPARSE memory access.
-
- see include/asm-alpha/mcpcia.h for the SPARSE mem read/write
- */
- mcpcia_sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;/* reg 1 */
- mcpcia_sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;/* reg 2 */
- mcpcia_sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;/* reg 3 */
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in mcpcia.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = mcpcia_hae_mem;
-#else /* SRM_SETUP */
- *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
- mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
- *(vuip)MCPCIA_HAE_IO(h) = 0; mb();
- mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h);
-#endif /* SRM_SETUP */
- }
- } /* end for-loop on hoses */
- return mem_start;
-}
-
-int mcpcia_pci_clr_err(int h)
-{
- unsigned int cpu = smp_processor_id();
-
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
-#if 0
- DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
- h, MCPCIA_jd[cpu]));
-#endif
- *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
- return 0;
-}
-
-static void
-mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
-{
- struct el_common_EV5_uncorrectable_mcheck *frame;
- int i;
-
- frame = &logout->procdata;
-
- /* Print PAL fields */
- for (i = 0; i < 24; i += 2) {
- printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r",
- i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
- }
- for (i = 0; i < 8; i += 2) {
- printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r",
- i, i+1, frame->shadow[i],
- frame->shadow[i+1]);
- }
- printk("\tAddr of excepting instruction\t= %16lx\n\r",
- frame->exc_addr);
- printk("\tSummary of arithmetic traps\t= %16lx\n\r",
- frame->exc_sum);
- printk("\tException mask\t\t\t= %16lx\n\r",
- frame->exc_mask);
- printk("\tBase address for PALcode\t= %16lx\n\r",
- frame->pal_base);
- printk("\tInterrupt Status Reg\t\t= %16lx\n\r",
- frame->isr);
- printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r",
- frame->icsr);
- printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r",
- (frame->ic_perr_stat & 0x800L) ?
- "Data" : "Tag",
- frame->ic_perr_stat);
- printk("\tD-CACHE error Reg\t\t= %16lx\n\r",
- frame->dc_perr_stat);
- if (frame->dc_perr_stat & 0x2) {
- switch (frame->dc_perr_stat & 0x03c) {
- case 8:
- printk("\t\tData error in bank 1\n\r");
- break;
- case 4:
- printk("\t\tData error in bank 0\n\r");
- break;
- case 20:
- printk("\t\tTag error in bank 1\n\r");
- break;
- case 10:
- printk("\t\tTag error in bank 0\n\r");
- break;
- }
- }
- printk("\tEffective VA\t\t\t= %16lx\n\r",
- frame->va);
- printk("\tReason for D-stream\t\t= %16lx\n\r",
- frame->mm_stat);
- printk("\tEV5 SCache address\t\t= %16lx\n\r",
- frame->sc_addr);
- printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r",
- frame->sc_stat);
- printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r",
- frame->bc_tag_addr);
- printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r",
- frame->ei_addr);
- printk("\tFill Syndrome\t\t\t= %16lx\n\r",
- frame->fill_syndrome);
- printk("\tEI_STAT reg\t\t\t= %16lx\n\r",
- frame->ei_stat);
- printk("\tLD_LOCK\t\t\t\t= %16lx\n\r",
- frame->ld_lock);
-}
-
-void mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
- struct pt_regs * regs)
-{
-#if 0
- printk("mcpcia machine check ignored\n") ;
-#else
- struct el_common *mchk_header;
- struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
- unsigned int cpu = smp_processor_id();
- int h = 0;
-
- mchk_header = (struct el_common *)la_ptr;
- mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
-
-#if 0
- DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
- type, la_ptr));
- DBG_MCK(("\t\t 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));
-#endif
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (MCPCIA_mcheck_expected[cpu]) {
-#if 0
- DBG_MCK(("MCPCIA machine check expected\n"));
-#endif
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
- DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
- " code=0x%lx\n",
- type, regs->pc, mchk_header->code));
-
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
-#ifdef DEBUG_MCHECK_DUMP
- if (type == 0x620)
- printk("MCPCIA machine check: system CORRECTABLE!\n");
- else if (type == 0x630)
- printk("MCPCIA machine check: processor CORRECTABLE!\n");
- else
- mcpcia_print_uncorrectable(mchk_logout);
-#endif /* DEBUG_MCHECK_DUMP */
- }
-#endif
-#endif
-}
-
-/*==========================================================================*/
-
-#define PRIMARY(b) ((b)&0xff)
-#define SECONDARY(b) (((b)>>8)&0xff)
-#define SUBORDINATE(b) (((b)>>16)&0xff)
-
-static int
-hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
- unsigned int found = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- hose_read_config_byte(hose, bus, devfn,
- PCI_HEADER_TYPE, &hdr_type);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- hose_read_config_dword(hose, bus, devfn,
- PCI_CLASS_REVISION, &class);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- found++;
-
- hose_read_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, &busses);
-
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d busses 0x%x\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), busses));
- /*
- * do something with first_busno and last_busno
- */
- if (hose->pci_first_busno > PRIMARY(busses)) {
- hose->pci_first_busno = PRIMARY(busses);
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change first to %d\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), PRIMARY(busses)));
- }
- if (hose->pci_last_busno < SUBORDINATE(busses)) {
- hose->pci_last_busno = SUBORDINATE(busses);
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change last to %d\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), SUBORDINATE(busses)));
- }
- /*
- * Now scan everything underneath the bridge.
- */
- hose_scan_bridges(hose, SECONDARY(busses));
- }
- }
- return found;
-}
-
-static void
-hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- hose_read_config_byte(hose, bus, devfn,
- PCI_HEADER_TYPE, &hdr_type);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- hose_read_config_dword(hose, bus, devfn,
- PCI_CLASS_REVISION, &class);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- hose_read_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, &busses);
-
- /*
- * First reconfigure everything underneath the bridge.
- */
- hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
-
- /*
- * Unconfigure this bridges bus numbers,
- * pci_scan_bus() will fix this up properly.
- */
- busses &= 0xff000000;
- hose_write_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, busses);
- }
- }
-}
-
-static void mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int nbus;
-
- /*
- * First, scan for all bridge devices underneath this hose,
- * to determine the first and last busnos.
- */
- if (!hose_scan_bridges(hose, 0)) {
- /* none found, exit */
- hose->pci_first_busno = bus;
- hose->pci_last_busno = bus;
- } else {
- /*
- * Reconfigure all bridge devices underneath this hose.
- */
- hose_reconfigure_bridges(hose, hose->pci_first_busno);
- }
-
- /*
- * Now reconfigure the hose to it's new bus number and set up
- * our bus2hose mapping for this hose.
- */
- nbus = hose->pci_last_busno - hose->pci_first_busno;
-
- hose->pci_first_busno = bus;
-
-DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n",
- hose->pci_hose_index, bus, nbus));
-
- do {
- bus2hose[bus++] = hose;
- } while (nbus-- > 0);
-}
-
-static void mcpcia_probe(struct linux_hose_info *hose)
-{
- static struct pci_bus *pchain = NULL;
- struct pci_bus *pbus = &hose->pci_bus;
- static unsigned char busno = 0;
-
- /* Hoses include child PCI bridges in bus-range property,
- * but we don't scan each of those ourselves, Linux generic PCI
- * probing code will find child bridges and link them into this
- * hose's root PCI device hierarchy.
- */
-
- pbus->number = pbus->secondary = busno;
- pbus->sysdata = hose;
-
- mcpcia_fixup_busno(hose, busno);
-
- pbus->subordinate = pci_scan_bus(pbus); /* the original! */
-
- /*
- * Set the maximum subordinate bus of this hose.
- */
- hose->pci_last_busno = pbus->subordinate;
-#if 0
- hose_write_config_byte(hose, busno, 0, 0x41, hose->pci_last_busno);
-#endif
- busno = pbus->subordinate + 1;
-
- /*
- * Fixup the chain of primary PCI busses.
- */
- if (pchain) {
- pchain->next = &hose->pci_bus;
- pchain = pchain->next;
- } else {
- pchain = &pci_root;
- memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
- }
-}
-
-void mcpcia_fixup(void)
-{
- struct linux_hose_info *hose;
-
- /* turn on Config space access finally! */
- pci_probe_enabled = 1;
-
- /* for each hose, probe and setup the devices on the hose */
- for (hose = mcpcia_root; hose; hose = hose->next)
- mcpcia_probe(hose);
-}
-#endif /* CONFIG_ALPHA_MCPCIA */
extern kdev_t get_unnamed_dev(void);
extern void put_unnamed_dev(kdev_t);
-extern asmlinkage int sys_umount(char *);
+extern asmlinkage int sys_umount(char *, int);
extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
extern asmlinkage unsigned long sys_brk(unsigned long);
int ret;
lock_kernel();
- ret = sys_umount(path);
+ ret = sys_umount(path,flag);
unlock_kernel();
return ret;
}
#include <linux/mman.h>
#include <linux/elfcore.h>
#include <linux/reboot.h>
+#include <linux/console.h>
#ifdef CONFIG_RTC
#include <linux/mc146818rtc.h>
#include <asm/hwrpb.h>
#include <asm/fpu.h>
+#include "proto.h"
+#include "bios32.h"
+
/*
* Initial task structure. Make this a per-architecture thing,
* because different architectures tend to have different
/*
* No need to acquire the kernel lock, we're entirely local..
*/
-asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage int
+sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
-#if !defined(CONFIG_ALPHA_TSUNAMI)
(®s)->hae = hae;
-#endif
return 0;
}
#ifdef __SMP__
/* This is being executed in task 0 'user space'. */
#define resched_needed() 1
-int cpu_idle(void *unused)
+int
+cpu_idle(void *unused)
{
extern volatile int smp_commenced;
}
}
-asmlinkage int sys_idle(void)
+asmlinkage int
+sys_idle(void)
{
if(current->pid != 0)
return -EPERM;
#else /* __SMP__ */
-asmlinkage int sys_idle(void)
+asmlinkage int
+sys_idle(void)
{
int ret = -EPERM;
}
#endif /* __SMP__ */
-#if defined(CONFIG_ALPHA_SRM_SETUP)
-extern void reset_for_srm(void);
-extern unsigned long srm_hae;
-#endif
-
-static void finish_shutdown(void)
+void
+generic_kill_arch (int mode, char *restart_cmd)
{
-#ifdef CONFIG_RTC /* reset rtc to defaults */
- unsigned char control;
- unsigned long flags;
-
- /* i'm not sure if i really need to disable interrupts here */
- save_and_cli(flags);
-
- /* reset periodic interrupt frequency */
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
-
- /* turn on periodic interrupts */
- control = CMOS_READ(RTC_CONTROL);
- control |= RTC_PIE;
- CMOS_WRITE(control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
- restore_flags(flags);
+ /* The following currently only has any effect on SRM. We should
+ fix MILO to understand it. Should be pretty easy. Also we can
+ support RESTART2 via the ipc_buffer machinations pictured below,
+ which SRM ignores. */
+
+ if (alpha_using_srm) {
+ struct percpu_struct *cpup;
+ unsigned long flags;
+
+ cpup = (struct percpu_struct *)
+ ((unsigned long)hwrpb + hwrpb->processor_offset);
+
+ flags = cpup->flags;
+
+ /* Clear reason to "default"; clear "bootstrap in progress". */
+ flags &= ~0x00ff0001UL;
+
+ if (mode == LINUX_REBOOT_CMD_RESTART) {
+ if (!restart_cmd) {
+ flags |= 0x00020000UL; /* "cold bootstrap" */
+ cpup->ipc_buffer[0] = 0;
+ } else {
+ flags |= 0x00030000UL; /* "warm bootstrap" */
+ strncpy(cpup->ipc_buffer, restart_cmd,
+ sizeof(cpup->ipc_buffer));
+ }
+ }
+ else {
+ flags |= 0x00040000UL; /* "remain halted" */
+ }
+
+ cpup->flags = flags;
+ mb();
+
+ if (alpha_use_srm_setup) {
+ reset_for_srm();
+ set_hae(srm_hae);
+ }
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ /* This has the effect of reseting the VGA video origin. */
+ take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
#endif
-#if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR)
- /* who said DEC engineer's have no sense of humor? ;-)) */
- *(int *) GRU_RESET = 0x0000dead;
- mb();
+ }
+
+#ifdef CONFIG_RTC
+ /* Reset rtc to defaults. */
+ {
+ unsigned char control;
+ unsigned long flags;
+
+ /* I'm not sure if i really need to disable interrupts here. */
+ save_and_cli(flags);
+
+ /* Reset periodic interrupt frequency. */
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+
+ /* Turn on periodic interrupts. */
+ control = CMOS_READ(RTC_CONTROL);
+ control |= RTC_PIE;
+ CMOS_WRITE(control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+
+ restore_flags(flags);
+ }
#endif
+
+ if (!alpha_using_srm && mode != LINUX_REBOOT_CMD_RESTART) {
+ /* Unfortunately, since MILO doesn't currently understand
+ the hwrpb bits above, we can't reliably halt the
+ processor and keep it halted. So just loop. */
+ return;
+ }
+
halt();
}
-void machine_restart(char * __unused)
+void
+machine_restart(char *restart_cmd)
{
-#if defined(CONFIG_ALPHA_SRM)
- extern struct hwrpb_struct *hwrpb;
- struct percpu_struct *cpup;
- unsigned long flags;
-
- cpup = (struct percpu_struct *)
- ((unsigned long)hwrpb + hwrpb->processor_offset);
- flags = cpup->flags;
- flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */
- flags |= 0x0000000000020000UL; /* this is "cold bootstrap" */
-/* flags |= 0x0000000000030000UL; *//* this is "warm bootstrap" */
- cpup->flags = flags;
- mb();
-#if defined(CONFIG_ALPHA_SRM_SETUP)
- reset_for_srm();
- set_hae(srm_hae);
-#endif
-#endif /* SRM */
-
- finish_shutdown();
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_RESTART, restart_cmd);
}
-void machine_halt(void)
+void
+machine_halt(void)
{
-#if defined(CONFIG_ALPHA_SRM)
- extern struct hwrpb_struct *hwrpb;
- struct percpu_struct *cpup;
- unsigned long flags;
-
- cpup = (struct percpu_struct *)
- ((unsigned long)hwrpb + hwrpb->processor_offset);
- flags = cpup->flags;
- flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */
- flags |= 0x0000000000040000UL; /* this is "remain halted" */
- cpup->flags = flags;
- mb();
-#if defined(CONFIG_ALPHA_SRM_SETUP)
- reset_for_srm();
- set_hae(srm_hae);
-#endif
-
- finish_shutdown();
-#endif /* SRM */
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_HALT, NULL);
}
void machine_power_off(void)
{
- /* None of the machines we support, at least, has switchable
- power supplies. */
- machine_halt();
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_POWER_OFF, NULL);
}
void show_regs(struct pt_regs * regs)
--- /dev/null
+/* Prototypes of functions used across modules here in this directory. */
+
+#define vucp volatile unsigned char *
+#define vusp volatile unsigned short *
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+/* core_apecs.c */
+extern int apecs_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int apecs_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int apecs_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int apecs_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int apecs_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int apecs_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void apecs_init_arch(unsigned long *, unsigned long *);
+
+extern volatile unsigned int apecs_mcheck_expected;
+extern volatile unsigned int apecs_mcheck_taken;
+extern int apecs_pci_clr_err(void);
+extern void apecs_machine_check(u64, u64, struct pt_regs *);
+
+/* core_cia.c */
+extern int cia_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int cia_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int cia_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int cia_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int cia_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int cia_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void cia_init_arch(unsigned long *, unsigned long *);
+extern void cia_machine_check(u64, u64, struct pt_regs *);
+
+/* core_lca.c */
+extern int lca_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int lca_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int lca_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int lca_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int lca_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int lca_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void lca_init_arch(unsigned long *, unsigned long *);
+extern void lca_machine_check(u64, u64, struct pt_regs *);
+
+/* core_mcpcia.c */
+extern int mcpcia_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int mcpcia_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int mcpcia_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int mcpcia_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int mcpcia_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int mcpcia_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void mcpcia_init_arch(unsigned long *, unsigned long *);
+extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
+extern void mcpcia_pci_fixup(void);
+
+/* core_pyxis.c */
+extern int pyxis_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int pyxis_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int pyxis_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int pyxis_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int pyxis_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int pyxis_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void pyxis_enable_errors (void);
+extern int pyxis_srm_window_setup (void);
+extern void pyxis_native_window_setup(void);
+extern void pyxis_finish_init_arch(void);
+extern void pyxis_init_arch(unsigned long *, unsigned long *);
+extern void pyxis_machine_check(u64, u64, struct pt_regs *);
+
+/* core_t2.c */
+extern int t2_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int t2_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int t2_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int t2_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int t2_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int t2_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void t2_init_arch(unsigned long *, unsigned long *);
+extern void t2_machine_check(u64, u64, struct pt_regs *);
+
+/* core_tsunami.c */
+extern int tsunami_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int tsunami_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int tsunami_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int tsunami_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int tsunami_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int tsunami_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void tsunami_init_arch(unsigned long *, unsigned long *);
+extern void tsunami_machine_check(u64, u64, struct pt_regs *);
+
+/* setup.c */
+extern void init_pit_rest(void);
+extern void generic_init_pit (void);
+extern unsigned long srm_hae;
+
+/* smp.c */
+extern void setup_smp(void);
+extern char *smp_info(void);
+extern void handle_ipi(struct pt_regs *);
+
+/* bios32.c */
+extern void reset_for_srm(void);
+
+/* time.c */
+extern void timer_interrupt(struct pt_regs * regs);
+
+/* smc37c93x.c */
+extern void SMC93x_Init(void);
+
+/* smc37c669.c */
+extern void SMC669_Init(void);
+
+/* es1888.c */
+extern void es1888_init(void);
+
+/* fpregs.c */
+extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
+extern unsigned long alpha_read_fp_reg (unsigned long reg);
+
+/* head.S */
+extern void wrmces(unsigned long mces);
+extern void cserve_ena(unsigned long);
+extern void cserve_dis(unsigned long);
+
+/* entry.S */
+extern void entArith(void);
+extern void entIF(void);
+extern void entInt(void);
+extern void entMM(void);
+extern void entSys(void);
+extern void entUna(void);
+
+/* process.c */
+void generic_kill_arch (int mode, char *reboot_cmd);
struct vm_area_struct * vma = find_extend_vma(tsk, addr);
DBG(DBG_MEM_ALL, ("in read_long\n"));
- if (!vma) {
- printk("Unable to find vma for addr 0x%lx\n",addr);
+ if (!vma)
return -EIO;
- }
if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
struct vm_area_struct * vma_high = vma;
unsigned long low, align;
+++ /dev/null
-/*
- * Code common to all PYXIS chips.
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/config.h> /* CONFIG_ALPHA_RUFFIAN. */
-#include <linux/kernel.h>
-#include <linux/types.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>
-
-/* NOTE: Herein are back-to-back mb instructions. They are magic.
- One plausible explanation is that the I/O controller does not properly
- handle the system transaction. Another involves timing. Ho hum. */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef DEBUG
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
-static volatile unsigned int PYXIS_mcheck_expected = 0;
-static volatile unsigned int PYXIS_mcheck_taken = 0;
-static unsigned int PYXIS_jd;
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
-unsigned int PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
-unsigned long pyxis_sm_base_r1, pyxis_sm_base_r2, pyxis_sm_base_r3;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the PYXIS_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 = device_fn >> 3;
- /* type 0 configuration cycle: */
-#if NOT_NOW
- if (device > 20) {
- DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
- device));
- return -1;
- }
-#endif
- *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, temp;
- unsigned int pyxis_cfg = 0; /* to keep gcc quiet */
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
- DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0));
- /* if Type1 access, must set PYXIS CFG */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- DBG(("conf_read: TYPE1 access\n"));
- }
-
- mb();
- draina();
- PYXIS_mcheck_expected = 1;
- PYXIS_mcheck_taken = 0;
- mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
- if (PYXIS_mcheck_taken) {
- PYXIS_mcheck_taken = 0;
- value = 0xffffffffU;
- mb();
- }
- PYXIS_mcheck_expected = 0;
- mb();
-
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- 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, temp;
- unsigned int pyxis_cfg = 0; /* to keep gcc quiet */
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
- DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0));
- /* if Type1 access, must set PYXIS CFG */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- DBG(("conf_read: TYPE1 access\n"));
- }
-
- draina();
- PYXIS_mcheck_expected = 1;
- mb();
- /* access configuration space: */
- *(vuip)addr = value;
- mb();
- mb(); /* magic */
- temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */
- PYXIS_mcheck_expected = 0;
- mb();
-
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- 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 = PYXIS_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 = PYXIS_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 = PYXIS_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 = PYXIS_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 = PYXIS_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 = PYXIS_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 pyxis_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned int pyxis_err ;
-
-#if 0
-printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
-printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR);
-
-printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ);
-printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK);
-printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE);
-printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO);
-printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG);
-printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT);
-#endif
-
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
- pyxis_err = *(vuip)PYXIS_ERR_MASK;
- pyxis_err &= ~4;
- *(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
-
- pyxis_err = *(vuip)PYXIS_ERR ;
- pyxis_err |= 0x180; /* master/target abort */
- *(vuip)PYXIS_ERR = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W0_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T0_BASE == 0) &&
- ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 0 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W0_BASE,
- *(vuip)PYXIS_W0_MASK,
- *(vuip)PYXIS_T0_BASE);
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W1_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T1_BASE == 0) &&
- ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U))
-{
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 1 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W1_BASE,
- *(vuip)PYXIS_W1_MASK,
- *(vuip)PYXIS_T1_BASE);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W2_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T2_BASE == 0) &&
- ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 2 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W2_BASE,
- *(vuip)PYXIS_W2_MASK,
- *(vuip)PYXIS_T2_BASE);
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W3_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T3_BASE == 0) &&
- ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 3 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W3_BASE,
- *(vuip)PYXIS_W3_MASK,
- *(vuip)PYXIS_T3_BASE);
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
-#if defined(CONFIG_ALPHA_RUFFIAN)
-#if 1
- printk("pyxis_init: skipping window register rewrites... "
- " trust DeskStation firmware!\n");
-#endif
-#else /* RUFFIAN */
- /*
- * 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)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)PYXIS_T0_BASE = 0;
-
- *(vuip)PYXIS_W1_BASE = 0x0 ;
- *(vuip)PYXIS_W2_BASE = 0x0 ;
- *(vuip)PYXIS_W3_BASE = 0x0 ;
- mb();
-#endif /* RUFFIAN */
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("PYXIS_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- /*
- * Next, clear the PYXIS_CFG register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
- unsigned int pyxis_cfg, temp;
- pyxis_cfg = *(vuip)PYXIS_CFG; mb();
- if (pyxis_cfg != 0) {
-#if 1
- printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg);
-#endif
- *(vuip)PYXIS_CFG = 0; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
- }
-
- {
- unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
- unsigned int pyxis_hae_io = *(vuip)PYXIS_HAE_IO;
-#if 0
- printk("PYXIS_init: HAE_MEM was 0x%x\n", pyxis_hae_mem);
- printk("PYXIS_init: HAE_IO was 0x%x\n", pyxis_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * see include/asm-alpha/pyxis.h for the SPARSE mem read/write
- */
- pyxis_sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;/* region 1 */
- pyxis_sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;/* region 2 */
- pyxis_sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;/* region 3 */
-
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in pyxis.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = pyxis_hae_mem;
-#else /* SRM_SETUP */
- *(vuip)PYXIS_HAE_MEM = 0U; mb();
- pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
- *(vuip)PYXIS_HAE_IO = 0; mb();
- pyxis_hae_io = *(vuip)PYXIS_HAE_IO; /* re-read to force write */
-#endif /* SRM_SETUP */
- }
-
- /*
- * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
- * enabling byte/word PCI bus space(s) access.
- */
- {
- unsigned int ctrl1;
- ctrl1 = *(vuip) PYXIS_CTRL1;
- if (!(ctrl1 & 1)) {
-#if 1
- printk("PYXIS_init: enabling byte/word PCI space\n");
-#endif
- *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb();
- ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read to force write */
- }
- }
-
- return mem_start;
-}
-
-int pyxis_pci_clr_err(void)
-{
- PYXIS_jd = *(vuip)PYXIS_ERR;
- DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
- *(vuip)PYXIS_ERR = 0x0180; mb();
- PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */
- return 0;
-}
-
-void pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- struct el_common *mchk_header;
- struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t 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_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- 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_MCHECK_DUMP */
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (PYXIS_mcheck_expected) {
- DBG(("PYXIS machine check expected\n"));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("PYXIS machine check NOT expected\n") ;
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t 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));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
-}
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-/* Note: This is only used by MILO, AFAIK... */
-/*
- * The DeskStation Ruffian motherboard firmware does not place
- * the memory size in the PALimpure area. Therefore, we use
- * the Bank Configuration Registers in PYXIS to obtain the size.
- */
-unsigned long pyxis_get_bank_size(unsigned long offset)
-{
- unsigned long bank_addr, bank, ret = 0;
-
- /* Valid offsets are: 0x800, 0x840 and 0x880
- since Ruffian only uses three banks. */
- bank_addr = (unsigned long)PYXIS_MCR + offset;
- bank = *(vulp)bank_addr;
-
- /* Check BANK_ENABLE */
- if (bank & 0x01) {
- static unsigned long size[] = {
- 0x40000000UL, /* 0x00, 1G */
- 0x20000000UL, /* 0x02, 512M */
- 0x10000000UL, /* 0x04, 256M */
- 0x08000000UL, /* 0x06, 128M */
- 0x04000000UL, /* 0x08, 64M */
- 0x02000000UL, /* 0x0a, 32M */
- 0x01000000UL, /* 0x0c, 16M */
- 0x00800000UL, /* 0x0e, 8M */
- 0x80000000UL, /* 0x10, 2G */
- };
-
- bank = (bank & 0x1e) >> 1;
- if (bank < sizeof(size)/sizeof(*size))
- ret = size[bank];
- }
-
- return ret;
-}
-#endif /* CONFIG_ALPHA_RUFFIAN */
*/
/*
- * bootup setup stuff..
+ * Bootup setup stuff.
*/
-#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/mc146818rtc.h>
#include <linux/console.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
#ifdef CONFIG_RTC
#include <linux/timex.h>
#include <asm/dma.h>
#include <asm/io.h>
-extern void setup_smp(void);
-extern char *smp_info(void);
+
+#include "proto.h"
#if 1
# define DBG_SRM(args) printk args
# define DBG_SRM(args)
#endif
-struct hae hae = {
- 0,
- (unsigned long*) HAE_ADDRESS
-};
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
+struct hwrpb_struct *hwrpb;
unsigned long srm_hae;
-#endif
-struct hwrpb_struct *hwrpb;
+#ifdef CONFIG_ALPHA_GENERIC
+struct alpha_machine_vector alpha_mv;
+int alpha_using_srm, alpha_use_srm_setup;
+#endif
unsigned char aux_device_present = 0xaa;
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+static unsigned long find_end_memory(void);
+static struct alpha_machine_vector *get_sysvec(long, long, long);
+static struct alpha_machine_vector *get_sysvec_byname(const char *);
+static void get_sysnames(long, long, char **, char **);
+
/*
* This is setup by the secondary bootstrap loader. Because
* the zero page is zeroed out as soon as the vm system is
#define COMMAND_LINE ((char*)(PARAM + 0x0000))
#define COMMAND_LINE_SIZE 256
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
- char saved_command_line[COMMAND_LINE_SIZE];
+static char command_line[COMMAND_LINE_SIZE];
+char saved_command_line[COMMAND_LINE_SIZE];
+
/*
* The format of "screen_info" is strange, and due to early
* i386-setup code. This is just enough to make the console
* code think we're on a VGA color display.
*/
+
struct screen_info screen_info = {
-#if defined(CONFIG_ALPHA_BOOK1)
- /* the AlphaBook1 has LCD video fixed at 800x600, 37 rows and 100 cols */
- 0, 37, /* orig-x, orig-y */
- { 0, 0 }, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 100, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 37, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-#else
- 0, 25, /* orig-x, orig-y */
- 0, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 80, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 25, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-#endif
+ orig_x: 0,
+ orig_y: 25,
+ orig_video_cols: 80,
+ orig_video_lines: 25,
+ orig_video_isVGA: 1,
+ orig_video_points: 16
};
+
/*
* Initialize Programmable Interval Timers with standard values. Some
* drivers depend on them being initialized (e.g., joystick driver).
*/
-static void init_pit (void)
+
+/* It is (normally) only counter 1 that presents config problems, so
+ provide this support function to do the rest of the job. */
+
+void inline
+init_pit_rest(void)
{
#if 0
- /*
- * Leave refresh timer alone---nobody should depend on
- * a particular value anyway.
- */
- outb(0x54, 0x43); /* counter 1: refresh timer */
- outb(0x18, 0x41);
+ /* Leave refresh timer alone---nobody should depend on a
+ particular value anyway. */
+ outb(0x54, 0x43); /* counter 1: refresh timer */
+ outb(0x18, 0x41);
#endif
-#ifdef CONFIG_RTC /* setup interval timer if /dev/rtc is being used */
- outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
- outb(LATCH & 0xff, 0x40); /* LSB */
- outb(LATCH >> 8, 0x40); /* MSB */
- request_region(0x40, 0x20, "timer"); /* reserve pit */
-#else /* RTC */
-#if !defined(CONFIG_ALPHA_RUFFIAN)
- /* Ruffian depends on the system timer established in MILO!! */
- outb(0x36, 0x43); /* counter 0: system timer */
- outb(0x00, 0x40);
- outb(0x00, 0x40);
-#endif /* RUFFIAN */
- request_region(0x70, 0x10, "timer"); /* reserve rtc */
-#endif /* RTC */
-
- outb(0xb6, 0x43); /* counter 2: speaker */
- outb(0x31, 0x42);
- outb(0x13, 0x42);
+ outb(0xb6, 0x43); /* counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
+
+ if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) {
+ printk("Setting RTC_FREQ to 1024 Hz\n");
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+ }
}
-static unsigned long find_end_memory(void)
+#ifdef CONFIG_RTC
+static inline void
+rtc_init_pit (void)
{
- int i;
- unsigned long high = 0;
- struct memclust_struct * cluster;
- struct memdesc_struct * memdesc;
+ /* Setup interval timer if /dev/rtc is being used */
+ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb(LATCH & 0xff, 0x40); /* LSB */
+ outb(LATCH >> 8, 0x40); /* MSB */
+ request_region(0x40, 0x20, "timer"); /* reserve pit */
- memdesc = (struct memdesc_struct *)
- (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
- cluster = memdesc->cluster;
- for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
- unsigned long tmp;
- tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
- if (tmp > high)
- high = tmp;
- }
- /* round it up to an even number of pages.. */
- high = (high + PAGE_SIZE) & (PAGE_MASK*2);
- return PAGE_OFFSET + high;
+ init_pit_rest();
}
+#endif
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+void
+generic_init_pit (void)
{
- extern int _end;
+ outb(0x36, 0x43); /* counter 0: system timer */
+ outb(0x00, 0x40);
+ outb(0x00, 0x40);
+ request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */
- init_pit();
+ init_pit_rest();
+}
- if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) {
- printk("setup_arch: setting RTC_FREQ to 1024/sec\n");
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
- }
+/* This probably isn't Right, but it is what the old code did. */
+#if defined(CONFIG_RTC)
+# define init_pit rtc_init_pit
+#else
+# define init_pit alpha_mv.init_pit
+#endif
- hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
-#if !defined(CONFIG_ALPHA_TSUNAMI)
-#ifdef CONFIG_ALPHA_SRM_SETUP
- srm_hae = *hae.reg; /* save SRM setting for restoration */
- DBG_SRM(("setup_arch: old HAE base: 0x%016lx\n", srm_hae));
-#endif /* SRM_SETUP */
- set_hae(hae.cache); /* sync HAE register w/hae_cache */
-#endif /* !TSUNAMI */
+/*
+ * Declare all of the machine vectors.
+ */
- wrmces(0x7); /* reset enable correctable error reports */
+extern struct alpha_machine_vector alcor_mv;
+extern struct alpha_machine_vector alphabook1_mv;
+extern struct alpha_machine_vector avanti_mv;
+extern struct alpha_machine_vector cabriolet_mv;
+extern struct alpha_machine_vector dp264_mv;
+extern struct alpha_machine_vector eb164_mv;
+extern struct alpha_machine_vector eb64p_mv;
+extern struct alpha_machine_vector eb66_mv;
+extern struct alpha_machine_vector eb66p_mv;
+extern struct alpha_machine_vector jensen_mv;
+extern struct alpha_machine_vector lx164_mv;
+extern struct alpha_machine_vector miata_mv;
+extern struct alpha_machine_vector mikasa_mv;
+extern struct alpha_machine_vector mikasa_primo_mv;
+extern struct alpha_machine_vector noname_mv;
+extern struct alpha_machine_vector noritake_mv;
+extern struct alpha_machine_vector noritake_primo_mv;
+extern struct alpha_machine_vector p2k_mv;
+extern struct alpha_machine_vector pc164_mv;
+extern struct alpha_machine_vector rawhide_mv;
+extern struct alpha_machine_vector ruffian_mv;
+extern struct alpha_machine_vector sable_mv;
+extern struct alpha_machine_vector sable_gamma_mv;
+extern struct alpha_machine_vector sx164_mv;
+extern struct alpha_machine_vector takara_mv;
+extern struct alpha_machine_vector xl_mv;
+extern struct alpha_machine_vector xlt_mv;
+
+
+void __init
+setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p)
+{
+ extern char _end[];
+
+ struct alpha_machine_vector *vec = NULL;
+ struct percpu_struct *cpu;
+ char *type_name, *var_name, *p;
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
- command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
- /* Hack for Jensen... since we're restricted to 8 or 16
- * chars for boot flags depending on the boot mode,
- * we need some shorthand. This should do for
- * installation. Later we'll add other abbreviations
- * as well...
+ /*
+ * Locate the command line.
*/
+
+ /* Hack for Jensen... since we're restricted to 8 or 16 chars for
+ boot flags depending on the boot mode, we need some shorthand.
+ This should do for installation. Later we'll add other
+ abbreviations as well... */
if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
- strcpy(saved_command_line, command_line);
} else {
- strcpy(command_line, COMMAND_LINE);
- strcpy(saved_command_line, COMMAND_LINE);
+ strncpy(command_line, COMMAND_LINE, sizeof command_line);
+ command_line[sizeof(command_line)-1] = 0;
}
- printk("Command line: %s\n", command_line);
-
+ strcpy(saved_command_line, command_line);
*cmdline_p = command_line;
- *memory_start_p = (unsigned long) &_end;
- *memory_end_p = find_end_memory();
-#if defined(CONFIG_ALPHA_LCA)
- *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_CIA)
- *memory_start_p = cia_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_PYXIS)
- *memory_start_p = pyxis_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_T2)
- *memory_start_p = t2_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_TSUNAMI)
- *memory_start_p = tsunami_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_MCPCIA)
- *memory_start_p = mcpcia_init(*memory_start_p, *memory_end_p);
+ /*
+ * Process command-line arguments.
+ */
+
+ for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
+#ifndef alpha_use_srm_setup
+ /* Allow a command-line option to respect the
+ SRM's configuration. */
+ if (strncmp(p, "srm_setup=", 10) == 0) {
+ alpha_use_srm_setup = (p[10] != '0');
+ continue;
+ }
#endif
-#ifdef __SMP__
- setup_smp();
+ if (strncmp(p, "alpha_mv=", 9) == 0) {
+ vec = get_sysvec_byname(p+9);
+ continue;
+ }
+ }
+
+ /* Replace the command line, not that we've killed it with strtok. */
+ strcpy(command_line, saved_command_line);
+
+ /*
+ * Indentify and reconfigure for the current system.
+ */
+
+ get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
+ &type_name, &var_name);
+ if (*var_name == '0')
+ var_name = "";
+
+ if (!vec) {
+ cpu = (struct percpu_struct*)
+ ((char*)hwrpb + hwrpb->processor_offset);
+ vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation,
+ cpu->type);
+ }
+
+#ifdef CONFIG_ALPHA_GENERIC
+ if (!vec) {
+ panic("Unsupported system type: %s%s%s (%ld %ld)\n",
+ type_name, (*var_name ? " variation " : ""), var_name,
+ hwrpb->sys_type, hwrpb->sys_variation);
+ }
+ alpha_mv = *vec;
+
+ /* Assume that we've booted from SRM if we havn't booted from MILO.
+ Detect the later by looking for "MILO" in the system serial nr. */
+ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#else
+ /* Once we're sure we can reliably identify systems, we should
+ simply panic as we do above. */
+ if (vec != &alpha_mv) {
+ printk("WARNING: Not configured for system type: %s%s%s "
+ "(%ld %ld)\nContinuing with trepidation...\n",
+ type_name, (*var_name ? " variation " : ""), var_name,
+ hwrpb->sys_type, hwrpb->sys_variation);
+ }
#endif
+ /*
+ * Sync with the HAE
+ */
+
+ /* Save the SRM's current value for restoration. */
+ srm_hae = *alpha_mv.hae_register;
+ __set_hae(alpha_mv.hae_cache);
+
+ /* Reset enable correctable error reports. */
+ wrmces(0x7);
+
+ /* Find our memory. */
+ *memory_end_p = find_end_memory();
+ *memory_start_p = (unsigned long) _end;
+
+ /* Initialize the machine. Usually has to do with setting up
+ DMA windows and the like. */
+ if (alpha_mv.init_arch)
+ alpha_mv.init_arch(memory_start_p, memory_end_p);
+
+ /* Initialize the timers. */
+ init_pit();
+
+ /* Default root filesystem to sda2. */
+ ROOT_DEV = to_kdev_t(0x0802);
+
+ /*
+ * Give us a default console. TGA users will see nothing until
+ * chr_dev_init is called, rather late in the boot sequence.
+ */
+
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
conswitchp = &dummy_con;
#endif
#endif
-}
+ /* Delayed so that we've initialized the machine first. */
+ printk("Booting on %s%s%s using machine vector %s\n",
+ type_name, (*var_name ? " variation " : ""),
+ var_name, alpha_mv.vector_name);
+ printk("Command line: %s\n", command_line);
-#define N(a) (sizeof(a)/sizeof(a[0]))
+ /*
+ * Check ASN in HWRPB for validity, report if bad.
+ * FIXME: how was this failing? Should we trust it instead,
+ * and copy the value into alpha_mv.max_asn?
+ */
-/* A change was made to the HWRPB via an ECO and the following code tracks
- * a part of the ECO. In HWRPB versions less than 5, the ECO was not
- * implemented in the console firmware. If it's revision 5 or greater we can
- * get the name of the platform as an ASCII string from the HWRPB. That's what
- * this function does. It checks the revision level and if the string is in
- * the HWRPB it returns the address of the string--a pointer to the name of the
- * platform.
- *
- * Returns:
- * - Pointer to a ASCII string if it's in the HWRPB
- * - Pointer to a blank string if the data is not in the HWRPB.
- */
-static char *
-platform_string(void)
-{
- struct dsr_struct *dsr;
- static char unk_system_string[] = "N/A";
+ if (hwrpb->max_asn != MAX_ASN) {
+ printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn);
+ }
- /* Go to the console for the string pointer.
- * If the rpb_vers is not 5 or greater the rpb
- * is old and does not have this data in it.
+ /*
+ * Identify the flock of penguins.
*/
- if (hwrpb->revision < 5)
- return (unk_system_string);
- else {
- /* The Dynamic System Recognition struct
- * has the system platform name starting
- * after the character count of the string.
- */
- dsr = ((struct dsr_struct *)
- ((char *)hwrpb + hwrpb->dsr_offset));
- return ((char *)dsr + (dsr->sysname_off +
- sizeof(long)));
- }
+
+#ifdef __SMP__
+ setup_smp();
+#endif
}
-static void
-get_sysnames(long type, long variation,
- char **type_name, char **variation_name)
+static unsigned long __init
+find_end_memory(void)
{
- static char *sys_unknown = "Unknown";
- static char *systype_names[] = {
- "0",
- "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
- "Pelican", "Morgan", "Sable", "Medulla", "Noname",
- "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
- "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
- "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
- "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
- "Tsunami", "Wildfire", "CUSCO"
+ int i;
+ unsigned long high = 0;
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
+
+ memdesc = (struct memdesc_struct *)
+ (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+ cluster = memdesc->cluster;
+
+ for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
+ unsigned long tmp;
+ tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
+ if (tmp > high)
+ high = tmp;
+ }
+
+ /* Round it up to an even number of pages. */
+ high = (high + PAGE_SIZE) & (PAGE_MASK*2);
+ return PAGE_OFFSET + high;
+}
+
+
+static char sys_unknown[] = "Unknown";
+static char systype_names[][16] = {
+ "0",
+ "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
+ "Pelican", "Morgan", "Sable", "Medulla", "Noname",
+ "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
+ "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
+ "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
+ "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
+ "Tsunami", "Wildfire", "CUSCO"
+};
+
+static char unofficial_names[][8] = {"100", "Ruffian"};
+
+static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164"};
+static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
+
+static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"};
+static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
+
+static char eb64p_names[][16] = {"EB64+", "Cabriolet", "AlphaPCI64"};
+static int eb64p_indices[] = {0,0,1,2};
+
+static char eb66_names[][8] = {"EB66", "EB66+"};
+static int eb66_indices[] = {0,0,1};
+
+static char rawhide_names[][16] = {
+ "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
+};
+static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+
+
+static struct alpha_machine_vector * __init
+get_sysvec(long type, long variation, long cpu)
+{
+#ifdef CONFIG_ALPHA_GENERIC
+ static struct alpha_machine_vector *systype_vecs[] __initlocaldata =
+ {
+ NULL, /* 0 */
+ NULL, /* ADU */
+ NULL, /* Cobra */
+ NULL, /* Ruby */
+ NULL, /* Flamingo */
+ NULL, /* Mannequin */
+ &jensen_mv,
+ NULL, /* Pelican */
+ NULL, /* Morgan */
+ NULL, /* Sable -- see below. */
+ NULL, /* Medulla */
+ &noname_mv,
+ NULL, /* Turbolaser */
+ &avanti_mv,
+ NULL, /* Mustang */
+ &alcor_mv, /* Alcor, Bret, Maverick. */
+ NULL, /* Tradewind */
+ NULL, /* Mikasa -- see below. */
+ NULL, /* EB64 */
+ NULL, /* EB66 -- see variation. */
+ NULL, /* EB64+ -- see variation. */
+ &alphabook1_mv,
+ &rawhide_mv,
+ NULL, /* K2 */
+ NULL, /* Lynx */
+ &xl_mv,
+ NULL, /* EB164 -- see variation. */
+ NULL, /* Noritake -- see below. */
+ NULL, /* Cortex */
+ NULL, /* 29 */
+ &miata_mv,
+ NULL, /* XXM */
+ &takara_mv,
+ NULL, /* Yukon */
+ &dp264_mv,
+ NULL, /* Wildfire */
+ NULL, /* CUSCO */
+ };
+
+ static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
+ {
+ NULL, /* 100 */
+ &ruffian_mv,
+ };
+
+ static struct alpha_machine_vector *alcor_vecs[] __initlocaldata =
+ {
+ &alcor_mv, &xlt_mv, &xlt_mv
+ };
+
+ static struct alpha_machine_vector *eb164_vecs[] __initlocaldata =
+ {
+ &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv
+ };
+
+ static struct alpha_machine_vector *eb64p_vecs[] __initlocaldata =
+ {
+ &eb64p_mv,
+ &cabriolet_mv,
+ NULL /* AlphaPCI64 */
+ };
+
+ static struct alpha_machine_vector *eb66_vecs[] __initlocaldata =
+ {
+ &eb66_mv,
+ &eb66p_mv
};
- static char *unofficial_names[] = {"100", "Ruffian"};
+ /* ??? Do we need to distinguish between Rawhides? */
- static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"};
- static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
+ struct alpha_machine_vector *vec;
- static char * alcor_names[] = {"Alcor", "Maverick", "Bret"};
- static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
+ /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
+ if (type < 0)
+ type = -type;
+
+ /* Search the system tables first... */
+ vec = NULL;
+ if (type < N(systype_vecs)) {
+ vec = systype_vecs[type];
+ } else if ((type > ST_UNOFFICIAL_BIAS) &&
+ (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
+ vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
+ }
- static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"};
- static int eb64p_indices[] = {0,0,1,2};
+ /* If we've not found one, try for a variation. */
+
+ if (!vec) {
+ /* Member ID is a bit-field. */
+ long member = (variation >> 10) & 0x3f;
+
+ switch (type) {
+ case ST_DEC_ALCOR:
+ if (member < N(alcor_indices))
+ vec = alcor_vecs[alcor_indices[member]];
+ break;
+ case ST_DEC_EB164:
+ if (member < N(eb164_indices))
+ vec = eb164_vecs[eb164_indices[member]];
+ break;
+ case ST_DEC_EB64P:
+ if (member < N(eb64p_indices))
+ vec = eb64p_vecs[eb64p_indices[member]];
+ break;
+ case ST_DEC_EB66:
+ if (member < N(eb66_indices))
+ vec = eb66_vecs[eb66_indices[member]];
+ break;
+ case ST_DEC_1000:
+ if (cpu == EV5_CPU)
+ vec = &mikasa_primo_mv;
+ else
+ vec = &mikasa_mv;
+ break;
+ case ST_DEC_NORITAKE:
+ if (cpu == EV5_CPU)
+ vec = &noritake_primo_mv;
+ else
+ vec = &noritake_mv;
+ break;
+ case ST_DEC_2100_A500:
+ if (cpu == EV5_CPU)
+ vec = &sable_gamma_mv;
+ else
+ vec = &sable_mv;
+ break;
+ }
+ }
+ return vec;
+#else
+ /* TODO: verify that the system is of the type for which we
+ were configured. For now, cop out and return success. */
+ return &alpha_mv;
+#endif /* GENERIC */
+}
- static char * eb66_names[] = {"EB66", "EB66+"};
- static int eb66_indices[] = {0,0,1};
+static struct alpha_machine_vector * __init
+get_sysvec_byname(const char *name)
+{
+#ifdef CONFIG_ALPHA_GENERIC
+ static struct alpha_machine_vector *all_vecs[] __initlocaldata =
+ {
+ &alcor_mv,
+ &alphabook1_mv,
+ &avanti_mv,
+ &cabriolet_mv,
+ &dp264_mv,
+ &eb164_mv,
+ &eb64p_mv,
+ &eb66_mv,
+ &eb66p_mv,
+ &jensen_mv,
+ &lx164_mv,
+ &miata_mv,
+ &mikasa_mv,
+ &mikasa_primo_mv,
+ &noname_mv,
+ &noritake_mv,
+ &noritake_primo_mv,
+ &p2k_mv,
+ &pc164_mv,
+ &rawhide_mv,
+ &ruffian_mv,
+ &sable_mv,
+ &sable_gamma_mv,
+ &sx164_mv,
+ &takara_mv,
+ &xl_mv,
+ &xlt_mv
+ };
- static char * rawhide_names[] = {"Dodge", "Wrangler", "Durango",
- "Tincup", "DaVinci"};
- static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+ int i, n = sizeof(all_vecs)/sizeof(*all_vecs);
+ for (i = 0; i < n; ++i) {
+ struct alpha_machine_vector *mv = all_vecs[i];
+ if (strcasecmp(mv->vector_name, name) == 0)
+ return mv;
+ }
+ return NULL;
+#else
+ if (strcasecmp(alpha_mv.vector_name, name) == 0)
+ return &alpha_mv;
+ return NULL;
+#endif
+}
+static void
+get_sysnames(long type, long variation,
+ char **type_name, char **variation_name)
+{
long member;
/* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
break;
case ST_DEC_RAWHIDE:
if (member < N(rawhide_indices))
- *variation_name = rawhide_names[rawhide_indices[member]];
+ *variation_name = rawhide_names[rawhide_indices[member]];
break;
- } /* end family switch */
+ }
+}
+
+/*
+ * A change was made to the HWRPB via an ECO and the following code
+ * tracks a part of the ECO. In HWRPB versions less than 5, the ECO
+ * was not implemented in the console firmware. If it's revision 5 or
+ * greater we can get the name of the platform as an ASCII string from
+ * the HWRPB. That's what this function does. It checks the revision
+ * level and if the string is in the HWRPB it returns the address of
+ * the string--a pointer to the name of the platform.
+ *
+ * Returns:
+ * - Pointer to a ASCII string if it's in the HWRPB
+ * - Pointer to a blank string if the data is not in the HWRPB.
+ */
+
+static char *
+platform_string(void)
+{
+ struct dsr_struct *dsr;
+ static char unk_system_string[] = "N/A";
+
+ /* Go to the console for the string pointer.
+ * If the rpb_vers is not 5 or greater the rpb
+ * is old and does not have this data in it.
+ */
+ if (hwrpb->revision < 5)
+ return (unk_system_string);
+ else {
+ /* The Dynamic System Recognition struct
+ * has the system platform name starting
+ * after the character count of the string.
+ */
+ dsr = ((struct dsr_struct *)
+ ((char *)hwrpb + hwrpb->dsr_offset));
+ return ((char *)dsr + (dsr->sysname_off +
+ sizeof(long)));
+ }
}
/*
*/
int get_cpuinfo(char *buffer)
{
- static char *cpu_names[] = {
- "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56",
- "EV6", "PCA56", "PCA57"
- };
-
extern struct unaligned_stat {
unsigned long count, va, pc;
} unaligned[2];
+ static char cpu_names[][8] = {
+ "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56",
+ "EV6", "PCA56", "PCA57"
+ };
+
struct percpu_struct *cpu;
unsigned int cpu_index;
char *cpu_name;
char *systype_name;
char *sysvariation_name;
+ int len;
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
cpu_index = (unsigned) (cpu->type - 1);
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&systype_name, &sysvariation_name);
- return sprintf(buffer,
- "cpu\t\t\t: Alpha\n"
- "cpu model\t\t: %s\n"
- "cpu variation\t\t: %ld\n"
- "cpu revision\t\t: %ld\n"
- "cpu serial number\t: %s\n"
- "system type\t\t: %s\n"
- "system variation\t: %s\n"
- "system revision\t\t: %ld\n"
- "system serial number\t: %s\n"
- "cycle frequency [Hz]\t: %lu\n"
- "timer frequency [Hz]\t: %lu.%02lu\n"
- "page size [bytes]\t: %ld\n"
- "phys. address bits\t: %ld\n"
- "max. addr. space #\t: %ld\n"
- "BogoMIPS\t\t: %lu.%02lu\n"
- "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
- "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
- "platform string\t\t: %s\n"
-#ifdef __SMP__
- "%s"
-#endif
- ,
-
+ len = sprintf(buffer,
+ "cpu\t\t\t: Alpha\n"
+ "cpu model\t\t: %s\n"
+ "cpu variation\t\t: %ld\n"
+ "cpu revision\t\t: %ld\n"
+ "cpu serial number\t: %s\n"
+ "system type\t\t: %s\n"
+ "system variation\t: %s\n"
+ "system revision\t\t: %ld\n"
+ "system serial number\t: %s\n"
+ "cycle frequency [Hz]\t: %lu\n"
+ "timer frequency [Hz]\t: %lu.%02lu\n"
+ "page size [bytes]\t: %ld\n"
+ "phys. address bits\t: %ld\n"
+ "max. addr. space #\t: %ld\n"
+ "BogoMIPS\t\t: %lu.%02lu\n"
+ "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "platform string\t\t: %s\n",
cpu_name, cpu->variation, cpu->revision,
(char*)cpu->serial_no,
systype_name, sysvariation_name, hwrpb->sys_revision,
loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
unaligned[0].count, unaligned[0].pc, unaligned[0].va,
unaligned[1].count, unaligned[1].pc, unaligned[1].va,
- platform_string()
+ platform_string());
+
#ifdef __SMP__
- , smp_info()
+ return len + smp_info(buffer+len);
+#else
+ return len;
#endif
- );
}
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
+#include "proto.h"
+
struct ipi_msg_flush_tb_struct ipi_msg_flush_tb;
struct cpuinfo_alpha cpu_data[NR_CPUS];
}
}
-static char smp_buf[256];
-
-char *smp_info(void)
+int smp_info(char *buffer)
{
- sprintf(smp_buf, "CPUs probed %d active %d map 0x%x AKP %d\n",
- smp_num_probed, smp_num_cpus, cpu_present_map,
- klock_info.akp);
-
- return smp_buf;
+ return sprintf(buffer, "CPUs probed %d active %d map 0x%x AKP %d\n",
+ smp_num_probed, smp_num_cpus, cpu_present_map,
+ klock_info.akp);
}
/* wrapper for call from panic() */
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_alcor.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the ALCOR and XLT (XL-300/366/433).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+alcor_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* On Alcor, at least, lines 20..30 are not connected and can
+ generate spurrious interrupts if we turn them on while IRQ
+ probing. So explicitly mask them out. */
+ mask |= 0x7ff000000000UL;
+
+ /* Note inverted sense of mask bits: */
+ *(vuip)GRU_INT_MASK = ~(mask >> 16);
+ mb();
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+alcor_ack_irq(unsigned long irq)
+{
+ if (irq < 16) {
+ /* Ack the interrupt making it the lowest priority */
+ /* First the slave .. */
+ if (irq > 7) {
+ outb(0xE0 | (irq - 8), 0xa0);
+ irq = 2;
+ }
+ /* .. then the master */
+ outb(0xE0 | irq, 0x20);
+
+ /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
+ *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
+ *(vuip)GRU_INT_CLEAR = 0x00000000; mb();
+ }
+}
+
+static void
+alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of the GRU */
+ pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 31) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+alcor_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ *(vuip)GRU_INT_MASK = ~(alpha_irq_mask >> 16); mb(); /* invert */
+ *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */
+ *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
+ *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */
+
+ enable_irq(16 + 31); /* enable (E)ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ GRU_INT_REQ:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 2
+ * 1 Interrupt Line B from slot 2
+ * 2 Interrupt Line C from slot 2
+ * 3 Interrupt Line D from slot 2
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line C from slot 1
+ * 7 Interrupt Line D from slot 1
+ * 8 Interrupt Line A from slot 0
+ * 9 Interrupt Line B from slot 0
+ *10 Interrupt Line C from slot 0
+ *11 Interrupt Line D from slot 0
+ *12 Interrupt Line A from slot 4
+ *13 Interrupt Line B from slot 4
+ *14 Interrupt Line C from slot 4
+ *15 Interrupt Line D from slot 4
+ *16 Interrupt Line D from slot 3
+ *17 Interrupt Line D from slot 3
+ *18 Interrupt Line D from slot 3
+ *19 Interrupt Line D from slot 3
+ *20-30 Reserved
+ *31 EISA interrupt
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 6 built-in TULIP (XLT only)
+ * 7 PCI on board slot 0
+ * 8 PCI on board slot 3
+ * 9 PCI on board slot 4
+ * 10 PCEB (PCI-EISA bridge)
+ * 11 PCI on board slot 2
+ * 12 PCI on board slot 1
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+alcor_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[7][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ /* note: IDSEL 17 is XLT only */
+ {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
+ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
+ {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
+ {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
+ { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
+ { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
+ };
+ const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+alcor_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(alcor_map_irq, common_swizzle);
+}
+
+
+static void
+alcor_kill_arch (int mode, char *reboot_cmd)
+{
+ /* Who said DEC engineer's have no sense of humor? ;-) */
+ if (alpha_using_srm) {
+ *(vuip) GRU_RESET = 0x0000dead;
+ mb();
+ }
+
+ generic_kill_arch(mode, reboot_cmd);
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_ALCOR)
+struct alpha_machine_vector alcor_mv __initmv = {
+ vector_name: "Alcor",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: ALCOR_PROBE_MASK,
+ update_irq_hw: alcor_update_irq_hw,
+ ack_irq: alcor_ack_irq,
+ device_interrupt: alcor_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: alcor_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alcor_pci_fixup,
+ kill_arch: alcor_kill_arch,
+
+ sys: { cia: {
+ gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS
+ }}
+};
+ALIAS_MV(alcor)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XLT)
+struct alpha_machine_vector xlt_mv __initmv = {
+ vector_name: "XLT",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: ALCOR_PROBE_MASK,
+ update_irq_hw: alcor_update_irq_hw,
+ ack_irq: alcor_ack_irq,
+ device_interrupt: alcor_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: alcor_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alcor_pci_fixup,
+ kill_arch: alcor_kill_arch,
+
+ sys: { cia: {
+ gru_int_req_bits: XLT_GRU_INT_REQ_BITS
+ }}
+};
+ALIAS_MV(xlt)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_cabriolet.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
+ * PC164 and LX164.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+#include <asm/core_lca.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+cabriolet_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ outl(alpha_irq_mask >> 16, 0x804);
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+
+/* Under SRM console, we must use the CSERVE PALcode routine to manage
+ the interrupt mask for us. Otherwise, the kernel/HW get out of
+ sync with what the PALcode thinks it needs to deliver/ignore. */
+
+static void
+cabriolet_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmaskp)
+{
+ if (irq >= 16) {
+ if (unmaskp)
+ cserve_ena(irq - 16);
+ else
+ cserve_dis(irq - 16);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 4) {
+ isa_device_interrupt(v, r);
+ } else {
+ handle_irq(16 + i, 16 + i, r);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+cabriolet_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm) {
+ alpha_mv.update_irq_hw = cabriolet_srm_update_irq_hw;
+ alpha_mv.device_interrupt = srm_device_interrupt;
+ }
+ else {
+ outl(alpha_irq_mask >> 16, 0x804);
+ }
+
+ enable_irq(16 + 4); /* enable SIO cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * The EB66+ is very similar to the EB66 except that it does not have
+ * the on-board NCR and Tulip chips. In the code below, I have used
+ * slot number to refer to the id select line and *not* the slot
+ * number used in the EB66+ documentation. However, in the table,
+ * I've given the slot number, the id select line and the Jxx number
+ * that's printed on the board. The interrupt pins from the PCI slots
+ * are wired into 3 interrupt summary registers at 0x804, 0x805 and
+ * 0x806 ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number. This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+
+static inline int __init
+eb66p_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
+ {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
+ {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
+ };
+ const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+eb66p_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(eb66p_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+
+/*
+ * The AlphaPC64 is very similar to the EB66+ except that its slots
+ * are numbered differently. In the code below, I have used slot
+ * number to refer to the id select line and *not* the slot number
+ * used in the AlphaPC64 documentation. However, in the table, I've
+ * given the slot number, the id select line and the Jxx number that's
+ * printed on the board. The interrupt pins from the PCI slots are
+ * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
+ * ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number. This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+
+static inline int __init
+cabriolet_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
+ { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
+ { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+cabriolet_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(cabriolet_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+static inline void __init
+eb164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(cabriolet_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+
+/*
+ * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
+ * PCI slots, the SIO, PCI/IDE, and USB.
+ *
+ * Each of the interrupts can be individually masked. This is
+ * accomplished by setting the appropriate bit in the mask register.
+ * A bit is set by writing a "1" to the desired position in the mask
+ * register and cleared by writing a "0". There are 3 mask registers
+ * located at ISA address 804h, 805h and 806h.
+ *
+ * An I/O read at ISA address 804h, 805h, 806h will return the
+ * state of the 11 PCI interrupts and not the state of the MASKED
+ * interrupts.
+ *
+ * Note: A write to I/O 804h, 805h, and 806h the mask register will be
+ * updated.
+ *
+ *
+ * ISA DATA<7:0>
+ * ISA +--------------------------------------------------------------+
+ * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * +==============================================================+
+ * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
+ * +--------------------------------------------------------------+
+ * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
+ * +--------------------------------------------------------------+
+ * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
+ * +--------------------------------------------------------------+
+ * * Rsrv = reserved bits
+ * Note: The mask register is write-only.
+ *
+ * IdSel
+ * 5 32 bit PCI option slot 2
+ * 6 64 bit PCI option slot 0
+ * 7 64 bit PCI option slot 1
+ * 8 Saturn I/O
+ * 9 32 bit PCI option slot 3
+ * 10 USB
+ * 11 IDE
+ *
+ */
+
+static inline int __init
+alphapc164_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[7][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
+ { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
+ { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
+ { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
+ { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
+ };
+ const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+alphapc164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(alphapc164_map_irq, common_swizzle);
+ SMC93x_Init();
+}
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
+struct alpha_machine_vector cabriolet_mv __initmv = {
+ vector_name: "Cabriolet",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: cabriolet_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(cabriolet)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
+struct alpha_machine_vector eb164_mv __initmv = {
+ vector_name: "EB164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb164)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P)
+struct alpha_machine_vector eb66p_mv __initmv = {
+ vector_name: "EB66+",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb66p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb66p)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164)
+struct alpha_machine_vector lx164_mv __initmv = {
+ vector_name: "LX164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphapc164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(lx164)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
+struct alpha_machine_vector pc164_mv __initmv = {
+ vector_name: "PC164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphapc164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(pc164)
+#endif
+
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_dp264.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the DP264 (EV6+TSUNAMI).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_tsunami.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * HACK ALERT! only CPU#0 is used currently
+ */
+
+static void
+dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled */
+ *(vulp)TSUNAMI_CSR_DIM0 =
+ ~(mask) & ~0x0000000000000000UL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)TSUNAMI_CSR_DIM0;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+
+ /* Read the interrupt summary register of TSUNAMI */
+ pld = (*(vulp)TSUNAMI_CSR_DIR0);
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 55) {
+ isa_device_interrupt(vector, regs);
+ } else { /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+#if 0
+ *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb();
+ tmp = *(vulp)TSUNAMI_CSR_DIR0;
+#endif
+ }
+ __restore_flags(flags);
+}
+
+static void
+dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * The DP264 SRM console reports PCI interrupts with a vector
+ * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
+ * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have
+ * it line up with the actual bit numbers from the DIM registers,
+ * which is how we manage the interrupts/mask. Sigh...
+ */
+ if (irq >= 32)
+ ack = irq = irq - 16;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+dp264_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = dp264_srm_device_interrupt;
+
+ /* Note invert on MASK bits. */
+ *(vulp)TSUNAMI_CSR_DIM0 = ~(alpha_irq_mask) & ~0UL; mb();
+ *(vulp)TSUNAMI_CSR_DIM0;
+
+ enable_irq(55); /* Enable CYPRESS interrupt controller (ISA). */
+ enable_irq(2);
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ TSUNAMI_CSR_DIM0:
+ * Bit Meaning
+ * 0-17 Unused
+ *18 Interrupt SCSI B (Adaptec 7895 builtin)
+ *19 Interrupt SCSI A (Adaptec 7895 builtin)
+ *20 Interrupt Line D from slot 2 PCI0
+ *21 Interrupt Line C from slot 2 PCI0
+ *22 Interrupt Line B from slot 2 PCI0
+ *23 Interrupt Line A from slot 2 PCI0
+ *24 Interrupt Line D from slot 1 PCI0
+ *25 Interrupt Line C from slot 1 PCI0
+ *26 Interrupt Line B from slot 1 PCI0
+ *27 Interrupt Line A from slot 1 PCI0
+ *28 Interrupt Line D from slot 0 PCI0
+ *29 Interrupt Line C from slot 0 PCI0
+ *30 Interrupt Line B from slot 0 PCI0
+ *31 Interrupt Line A from slot 0 PCI0
+ *
+ *32 Interrupt Line D from slot 3 PCI1
+ *33 Interrupt Line C from slot 3 PCI1
+ *34 Interrupt Line B from slot 3 PCI1
+ *35 Interrupt Line A from slot 3 PCI1
+ *36 Interrupt Line D from slot 2 PCI1
+ *37 Interrupt Line C from slot 2 PCI1
+ *38 Interrupt Line B from slot 2 PCI1
+ *39 Interrupt Line A from slot 2 PCI1
+ *40 Interrupt Line D from slot 1 PCI1
+ *41 Interrupt Line C from slot 1 PCI1
+ *42 Interrupt Line B from slot 1 PCI1
+ *43 Interrupt Line A from slot 1 PCI1
+ *44 Interrupt Line D from slot 0 PCI1
+ *45 Interrupt Line C from slot 0 PCI1
+ *46 Interrupt Line B from slot 0 PCI1
+ *47 Interrupt Line A from slot 0 PCI1
+ *48-52 Unused
+ *53 PCI0 NMI (from Cypress)
+ *54 PCI0 SMI INT (from Cypress)
+ *55 PCI0 ISA Interrupt (from Cypress)
+ *56-60 Unused
+ *61 PCI1 Bus Error
+ *62 PCI0 Bus Error
+ *63 Reserved
+ *
+ * IdSel
+ * 5 Cypress Bridge I/O
+ * 6 SCSI Adaptec builtin
+ * 7 64 bit PCI option slot 0
+ * 8 64 bit PCI option slot 1
+ * 9 64 bit PCI option slot 2
+ *
+ */
+
+static int __init
+dp264_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
+ { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
+ { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
+ { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
+ { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+dp264_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(dp264_map_irq, common_swizzle);
+ SMC669_Init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector dp264_mv __initmv = {
+ vector_name: "DP264",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_TSUNAMI_IO,
+ DO_TSUNAMI_BUS,
+ machine_check: tsunami_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 64,
+ irq_probe_mask: _PROBE_MASK(64),
+ update_irq_hw: dp264_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: dp264_device_interrupt,
+
+ init_arch: tsunami_init_arch,
+ init_irq: dp264_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: dp264_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(dp264)
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_eb64p.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the EB64+ and EB66.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_lca.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+eb64p_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ if (irq >= 24)
+ outb(mask >> 24, 0x27);
+ else
+ outb(mask >> 16, 0x26);
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = inb(0x26) | (inb(0x27) << 8);
+ /*
+ * Now, for every possible bit set, work through
+ * them and call the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+
+ if (i == 5) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void __init
+eb64p_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ outb(alpha_irq_mask >> 16, 0x26);
+ outb(alpha_irq_mask >> 24, 0x27);
+ enable_irq(16 + 5); /* enable SIO cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * There are two 8 bit external summary registers as follows:
+ *
+ * Summary @ 0x26:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 0
+ * 1 Interrupt Line A from slot 1
+ * 2 Interrupt Line B from slot 0
+ * 3 Interrupt Line B from slot 1
+ * 4 Interrupt Line C from slot 0
+ * 5 Interrupt line from the two ISA PICs
+ * 6 Tulip (slot
+ * 7 NCR SCSI
+ *
+ * Summary @ 0x27
+ * Bit Meaning
+ * 0 Interrupt Line C from slot 1
+ * 1 Interrupt Line D from slot 0
+ * 2 Interrupt Line D from slot 1
+ * 3 RAZ
+ * 4 RAZ
+ * 5 RAZ
+ * 6 RAZ
+ * 7 RAZ
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 5 NCR SCSI controller
+ * 6 PCI on board slot 0
+ * 7 PCI on board slot 1
+ * 8 Intel SIO PCI-ISA bridge chip
+ * 9 Tulip - DECchip 21040 Ethernet controller
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+eb64p_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
+ {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
+ {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+eb64p_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(eb64p_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P)
+struct alpha_machine_vector eb64p_mv __initmv = {
+ vector_name: "EB64+",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: eb64p_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: eb64p_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: eb64p_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb64p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb64p)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66)
+struct alpha_machine_vector eb66_mv __initmv = {
+ vector_name: "EB66",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: eb64p_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: eb64p_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: eb64p_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb64p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb66)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_jensen.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Jensen.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/jensen.h>
+#undef __EXTERN_INLINE
+
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "machvec.h"
+
+
+static void
+jensen_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+/*
+ * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
+ * 0x9X0 for the local motherboard interrupts..
+ *
+ * 0x660 - NMI
+ *
+ * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
+ * 0x810 - IRQ1 line printer (duh..)
+ * 0x860 - IRQ6 floppy disk
+ * 0x8E0 - IRQ14 SCSI controller
+ *
+ * 0x900 - COM1
+ * 0x920 - COM2
+ * 0x980 - keyboard
+ * 0x990 - mouse
+ *
+ * PCI-based systems are more sane: they don't have the local
+ * interrupts at all, and have only normal PCI interrupts from
+ * devices. Happily it's easy enough to do a sane mapping from the
+ * Jensen.. Note that this means that we may have to do a hardware
+ * "ack" to a different interrupt than we report to the rest of the
+ * world.
+ */
+
+static void
+handle_nmi(struct pt_regs * regs)
+{
+ printk("Whee.. NMI received. Probable hardware error\n");
+ printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
+}
+
+static void
+jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ switch (vector) {
+ case 0x660: handle_nmi(regs); return;
+
+ /* local device interrupts: */
+ case 0x900: irq = 4, ack = -1; break; /* com1 -> irq 4 */
+ case 0x920: irq = 3, ack = -1; break; /* com2 -> irq 3 */
+ case 0x980: irq = 1, ack = -1; break; /* kbd -> irq 1 */
+ case 0x990: irq = 9, ack = -1; break; /* mouse -> irq 9 */
+ default:
+ if (vector > 0x900) {
+ printk("Unknown local interrupt %lx\n", vector);
+ }
+
+ /* irq1 is supposed to be the keyboard, silly Jensen
+ (is this really needed??) */
+ if (irq == 1)
+ irq = 7;
+ break;
+ }
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void
+jensen_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ enable_irq(2); /* enable cascade */
+}
+
+static void
+jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
+{
+ printk(KERN_CRIT "Machine check\n");
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector jensen_mv __initmv = {
+ vector_name: "Jensen",
+ DO_EV4_MMU,
+ IO_LITE(JENSEN,jensen,jensen),
+ BUS(jensen),
+ machine_check: jensen_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: jensen_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: jensen_device_interrupt,
+
+ init_arch: NULL,
+ init_irq: jensen_init_irq,
+ init_pit: generic_init_pit,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(jensen)
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_miata.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the MIATA (EV56+PYXIS).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+miata_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled... */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & ~0x4000000000000e3bUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+miata_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld, tmp;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /*
+ * For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8)
+ * then all the PCI slots/INTXs (12-31).
+ */
+ /* Maybe HALT should only be used for SRM console boots? */
+ pld &= 0x00000000fffff1c4UL;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ isa_device_interrupt(vector, regs);
+ } else if (i == 6) {
+ continue;
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ tmp = *(vulp)PYXIS_INT_REQ;
+ }
+ restore_flags(flags);
+}
+
+static void
+miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * I really hate to do this, but the MIATA SRM console ignores the
+ * low 8 bits in the interrupt summary register, and reports the
+ * vector 0x80 *lower* than I expected from the bit numbering in
+ * the documentation.
+ * This was done because the low 8 summary bits really aren't used
+ * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
+ * used for this purpose, as PIC interrupts are delivered as the
+ * vectors 0x800-0x8f0).
+ * But I really don't want to change the fixup code for allocation
+ * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which look
+ * nice and clean now.
+ * So, here's this grotty hack... :-(
+ */
+ if (irq >= 16)
+ ack = irq = irq + 8;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+miata_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = miata_srm_device_interrupt;
+
+ /* Note invert on MASK bits. */
+ *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16); mb();
+#if 0
+ /* These break on MiataGL so we'll try not to do it at all. */
+ *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
+ *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
+#endif
+ /* Clear upper timer. */
+ *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb();
+
+ enable_irq(16 + 2); /* enable HALT switch - SRM only? */
+ enable_irq(16 + 6); /* enable timer */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ PYXIS_INT_REQ:
+ * Bit Meaning
+ * 0 Fan Fault
+ * 1 NMI
+ * 2 Halt/Reset switch
+ * 3 none
+ * 4 CID0 (Riser ID)
+ * 5 CID1 (Riser ID)
+ * 6 Interval timer
+ * 7 PCI-ISA Bridge
+ * 8 Ethernet
+ * 9 EIDE (deprecated, ISA 14/15 used)
+ *10 none
+ *11 USB
+ *12 Interrupt Line A from slot 4
+ *13 Interrupt Line B from slot 4
+ *14 Interrupt Line C from slot 4
+ *15 Interrupt Line D from slot 4
+ *16 Interrupt Line A from slot 5
+ *17 Interrupt line B from slot 5
+ *18 Interrupt Line C from slot 5
+ *19 Interrupt Line D from slot 5
+ *20 Interrupt Line A from slot 1
+ *21 Interrupt Line B from slot 1
+ *22 Interrupt Line C from slot 1
+ *23 Interrupt Line D from slot 1
+ *24 Interrupt Line A from slot 2
+ *25 Interrupt Line B from slot 2
+ *26 Interrupt Line C from slot 2
+ *27 Interrupt Line D from slot 2
+ *27 Interrupt Line A from slot 3
+ *29 Interrupt Line B from slot 3
+ *30 Interrupt Line C from slot 3
+ *31 Interrupt Line D from slot 3
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 3 DC21142 Ethernet
+ * 4 EIDE CMD646
+ * 5 none
+ * 6 USB
+ * 7 PCI-ISA bridge
+ * 8 PCI-PCI Bridge (SBU Riser)
+ * 9 none
+ * 10 none
+ * 11 PCI on board slot 4 (SBU Riser)
+ * 12 PCI on board slot 5 (SBU Riser)
+ *
+ * These are behind the bridge, so I'm not sure what to do...
+ *
+ * 13 PCI on board slot 1 (SBU Riser)
+ * 14 PCI on board slot 2 (SBU Riser)
+ * 15 PCI on board slot 3 (SBU Riser)
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+miata_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[18][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
+ { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
+ { -1, -1, -1, -1, -1}, /* IdSel 16, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 17, none */
+ /* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, none */
+ {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
+ {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
+ /* The following are actually on bus 1, which is
+ across the builtin PCI-PCI bridge. */
+ {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */
+ {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */
+ {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */
+ { -1, -1, -1, -1, -1}, /* IdSel 27, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 28, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 29, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 30, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
+ };
+ const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static int __init
+miata_swizzle(struct pci_dev *dev, int *pinp)
+{
+ int slot, pin = *pinp;
+
+ /* Check first for the built-in bridge. */
+ if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+ (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+ slot = PCI_SLOT(dev->devfn) + 5;
+ }
+ else
+ {
+ /* Must be a card-based bridge. */
+ do {
+ if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+ (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+ slot = PCI_SLOT(dev->devfn) + 5;
+ break;
+ }
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ /* Slot of the next bridge. */
+ slot = PCI_SLOT(dev->devfn);
+ } while (dev->bus->self);
+ }
+ *pinp = pin;
+ return slot;
+}
+
+static void __init
+miata_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(miata_map_irq, miata_swizzle);
+ SMC669_Init(); /* it might be a GL (fails harmlessly if not) */
+ es1888_init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector miata_mv __initmv = {
+ vector_name: "Miata",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: miata_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: miata_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: miata_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: miata_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(miata)
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_mikasa.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the MIKASA (AlphaServer 1000).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+static void
+mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ outw(~(mask >> 16), 0x536); /* note invert */
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
+ (((unsigned long) inb(0xa0)) << 8) |
+ ((unsigned long) inb(0x20));
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i < 16) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(i, i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void __init
+mikasa_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ outw(~(alpha_irq_mask >> 16), 0x536); /* note invert */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ 0x536:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 0
+ * 1 Interrupt Line B from slot 0
+ * 2 Interrupt Line C from slot 0
+ * 3 Interrupt Line D from slot 0
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line C from slot 1
+ * 7 Interrupt Line D from slot 1
+ * 8 Interrupt Line A from slot 2
+ * 9 Interrupt Line B from slot 2
+ *10 Interrupt Line C from slot 2
+ *11 Interrupt Line D from slot 2
+ *12 NCR 810 SCSI
+ *13 Power Supply Fail
+ *14 Temperature Warn
+ *15 Reserved
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 6 NCR SCSI controller
+ * 7 Intel PCI-EISA bridge chip
+ * 11 PCI on board slot 0
+ * 12 PCI on board slot 1
+ * 13 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+mikasa_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[8][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
+ { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
+ { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
+ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
+ };
+ const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+mikasa_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(mikasa_map_irq, common_swizzle);
+}
+
+static void __init
+mikasa_primo_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(mikasa_map_irq, common_swizzle);
+}
+
+static void
+mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#define MCHK_NO_DEVSEL 0x205L
+#define MCHK_NO_TABT 0x204L
+
+ struct el_common *mchk_header;
+ struct el_apecs_procdata *mchk_procdata;
+ struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
+ unsigned long *ptr;
+ int i;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_procdata = (struct el_apecs_procdata *)
+ (la_ptr + mchk_header->proc_offset
+ - sizeof(mchk_procdata->paltemp));
+
+ mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#ifdef DEBUG
+ printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(" 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);
+ printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+ 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
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+
+ if (apecs_mcheck_expected
+ && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
+ || (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
+ apecs_mcheck_expected = 0;
+ apecs_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ apecs_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ draina();
+ }
+ else if (vector == 0x620 || vector == 0x630) {
+ /* Disable correctable from now on. */
+ wrmces(0x1f);
+ mb();
+ draina();
+ printk("mikasa_machine_check: HW correctable (0x%lx)\n",
+ vector);
+ }
+ else {
+ printk(KERN_CRIT "APECS machine check:\n");
+ printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(KERN_CRIT
+ " 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);
+ printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%lx %lx %lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+#if 0
+ /* doesn't work with MILO */
+ show_regs(regs);
+#endif
+ }
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector mikasa_mv __initmv = {
+ vector_name: "Mikasa",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: mikasa_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: mikasa_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: mikasa_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: mikasa_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: mikasa_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(mikasa)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector mikasa_primo_mv __initmv = {
+ vector_name: "Mikasa-Primo",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: mikasa_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: mikasa_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: mikasa_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: mikasa_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: mikasa_primo_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(mikasa_primo)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_noritake.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the NORITAKE (AlphaServer 1000A),
+ * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+noritake_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq <= 15)
+ if (irq <= 7)
+ outb(mask, 0x21); /* ISA PIC1 */
+ else
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else if (irq <= 31)
+ outw(~(mask >> 16), 0x54a);
+ else
+ outw(~(mask >> 32), 0x54c);
+}
+
+static void
+noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers of NORITAKE */
+ pld = ((unsigned long) inw(0x54c) << 32) |
+ ((unsigned long) inw(0x54a) << 16) |
+ ((unsigned long) inb(0xa0) << 8) |
+ ((unsigned long) inb(0x20));
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i < 16) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(i, i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * I really hate to do this, too, but the NORITAKE SRM console also
+ * reports PCI vectors *lower* than I expected from the bit numbers
+ * in the documentation.
+ * But I really don't want to change the fixup code for allocation
+ * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
+ * look nice and clean now.
+ * So, here's this additional grotty hack... :-(
+ */
+ if (irq >= 16)
+ ack = irq = irq + 1;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+noritake_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = noritake_srm_device_interrupt;
+
+ outw(~(alpha_irq_mask >> 16), 0x54a); /* note invert */
+ outw(~(alpha_irq_mask >> 32), 0x54c); /* note invert */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ 0x542, summary register #1:
+ * Bit Meaning
+ * 0 All valid ints from summary regs 2 & 3
+ * 1 QLOGIC ISP1020A SCSI
+ * 2 Interrupt Line A from slot 0
+ * 3 Interrupt Line B from slot 0
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line A from slot 2
+ * 7 Interrupt Line B from slot 2
+ * 8 Interrupt Line A from slot 3
+ * 9 Interrupt Line B from slot 3
+ *10 Interrupt Line A from slot 4
+ *11 Interrupt Line B from slot 4
+ *12 Interrupt Line A from slot 5
+ *13 Interrupt Line B from slot 5
+ *14 Interrupt Line A from slot 6
+ *15 Interrupt Line B from slot 6
+ *
+ * Summary @ 0x544, summary register #2:
+ * Bit Meaning
+ * 0 OR of all unmasked ints in SR #2
+ * 1 OR of secondary bus ints
+ * 2 Interrupt Line C from slot 0
+ * 3 Interrupt Line D from slot 0
+ * 4 Interrupt Line C from slot 1
+ * 5 Interrupt line D from slot 1
+ * 6 Interrupt Line C from slot 2
+ * 7 Interrupt Line D from slot 2
+ * 8 Interrupt Line C from slot 3
+ * 9 Interrupt Line D from slot 3
+ *10 Interrupt Line C from slot 4
+ *11 Interrupt Line D from slot 4
+ *12 Interrupt Line C from slot 5
+ *13 Interrupt Line D from slot 5
+ *14 Interrupt Line C from slot 6
+ *15 Interrupt Line D from slot 6
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 7 Intel PCI-EISA bridge chip
+ * 8 DEC PCI-PCI bridge chip
+ * 11 PCI on board slot 0
+ * 12 PCI on board slot 1
+ * 13 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+noritake_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[15][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ /* note: IDSELs 16, 17, and 25 are CORELLE only */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
+ { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
+ { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
+ { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
+ { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
+ { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
+ /* The following 5 are actually on PCI bus 1, which is
+ across the built-in bridge of the NORITAKE only. */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
+ { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
+ {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
+ {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
+ {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
+ };
+ const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static int __init
+noritake_swizzle(struct pci_dev *dev, int *pinp)
+{
+ int slot, pin = *pinp;
+
+ /* Check first for the built-in bridge */
+ if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+ slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
+ }
+ else
+ {
+ /* Must be a card-based bridge. */
+ do {
+ if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+ slot = PCI_SLOT(dev->devfn) + 15;
+ break;
+ }
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ /* Slot of the next bridge. */
+ slot = PCI_SLOT(dev->devfn);
+ } while (dev->bus->self);
+ }
+ *pinp = pin;
+ return slot;
+}
+
+static void __init
+noritake_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(noritake_map_irq, noritake_swizzle);
+}
+
+static void __init
+noritake_primo_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(noritake_map_irq, noritake_swizzle);
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector noritake_mv __initmv = {
+ vector_name: "Noritake",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: noritake_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: noritake_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: noritake_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noritake_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noritake)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector noritake_primo_mv __initmv = {
+ vector_name: "Noritake-Primo",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: noritake_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: noritake_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: noritake_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noritake_primo_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noritake_primo)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_rawhide.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the RAWHIDE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_mcpcia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 40) {
+ /* PCI bus 1 with builtin NCR810 SCSI */
+ *(vuip)MCPCIA_INT_MASK0(1) =
+ (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(1);
+ }
+ else if (irq >= 16) {
+ /* PCI bus 0 with EISA bridge */
+ *(vuip)MCPCIA_INT_MASK0(0) =
+ (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(0);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * The RAWHIDE SRM console reports PCI interrupts with a vector
+ * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
+ * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
+ * it line up with the actual bit numbers from the REQ registers,
+ * which is how we manage the interrupts/mask. Sigh...
+ *
+ * also, PCI #1 interrupts are offset some more... :-(
+ */
+ if (irq == 52)
+ ack = irq = 56; /* SCSI on PCI 1 is special */
+ else {
+ if (irq >= 24) /* adjust all PCI interrupts down 8 */
+ ack = irq = irq - 8;
+ if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */
+ ack = irq = irq - 8;
+ }
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+rawhide_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ /* HACK ALERT! only PCI busses 0 and 1 are used currently,
+ and routing is only to CPU #1*/
+
+ *(vuip)MCPCIA_INT_MASK0(0) =
+ (~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(0);
+
+ *(vuip)MCPCIA_INT_MASK0(1) =
+ (~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(1);
+
+ enable_irq(2);
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ MCPCIA_PCI0_INT_REQ:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 2 PCI0
+ * 1 Interrupt Line B from slot 2 PCI0
+ * 2 Interrupt Line C from slot 2 PCI0
+ * 3 Interrupt Line D from slot 2 PCI0
+ * 4 Interrupt Line A from slot 3 PCI0
+ * 5 Interrupt Line B from slot 3 PCI0
+ * 6 Interrupt Line C from slot 3 PCI0
+ * 7 Interrupt Line D from slot 3 PCI0
+ * 8 Interrupt Line A from slot 4 PCI0
+ * 9 Interrupt Line B from slot 4 PCI0
+ * 10 Interrupt Line C from slot 4 PCI0
+ * 11 Interrupt Line D from slot 4 PCI0
+ * 12 Interrupt Line A from slot 5 PCI0
+ * 13 Interrupt Line B from slot 5 PCI0
+ * 14 Interrupt Line C from slot 5 PCI0
+ * 15 Interrupt Line D from slot 5 PCI0
+ * 16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
+ * 17-23 NA
+ *
+ * IdSel
+ * 1 EISA bridge (PCI bus 0 only)
+ * 2 PCI option slot 2
+ * 3 PCI option slot 3
+ * 4 PCI option slot 4
+ * 5 PCI option slot 5
+ *
+ */
+
+static int __init
+rawhide_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */
+ { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
+ { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
+ { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
+ { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
+ };
+ const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP;
+ if (irq >= 0)
+ irq += 24 * bus2hose[dev->bus->number]->pci_hose_index;
+ return irq;
+}
+
+static void __init
+rawhide_pci_fixup(void)
+{
+ mcpcia_pci_fixup();
+ common_pci_fixup(rawhide_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector rawhide_mv __initmv = {
+ vector_name: "Rawhide",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_MCPCIA_IO,
+ DO_MCPCIA_BUS,
+ machine_check: mcpcia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 64,
+ irq_probe_mask: _PROBE_MASK(64),
+ update_irq_hw: rawhide_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: rawhide_srm_device_interrupt,
+
+ init_arch: mcpcia_init_arch,
+ init_irq: rawhide_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: rawhide_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(rawhide)
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_ruffian.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the RUFFIAN.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Note inverted sense of mask bits: */
+ /* Make CERTAIN none of the bogus ints get enabled... */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & 0x00000000ffffffbfUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+ruffian_ack_irq(unsigned long irq)
+{
+ if (irq < 16) {
+ /* Ack PYXIS ISA interrupt. */
+ *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_REQ;
+ if (irq > 7) {
+ outb(0x20, 0xa0);
+ }
+ outb(0x20, 0x20);
+ } else {
+ /* Ack PYXIS PCI interrupt. */
+ *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16));
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_REQ;
+ }
+}
+
+static void
+ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /* For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
+ * then all the PCI slots/INTXs (12-31)
+ * flash(5) :DWH:
+ */
+ pld &= 0x00000000ffffff9fUL; /* was ffff7f */
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ /* Copy this bit from isa_device_interrupt cause
+ we need to hook into int 0 for the timer. I
+ refuse to soil device_interrupt with ifdefs. */
+
+ /* Generate a PCI interrupt acknowledge cycle.
+ The PIC will respond with the interrupt
+ vector of the highest priority interrupt
+ that is pending. The PALcode sets up the
+ interrupts vectors such that irq level L
+ generates vector L. */
+
+ unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
+ if (j == 7 && !(inb(0x20) & 0x80)) {
+ /* It's only a passive release... */
+ } else if (j == 0) {
+ timer_interrupt(regs);
+ ruffian_ack_irq(0);
+ } else {
+ handle_irq(j, j, regs);
+ }
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ *(vulp)PYXIS_INT_REQ; /* read to force the write */
+ }
+ restore_flags(flags);
+}
+
+static void __init
+ruffian_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ /* Invert 6&7 for i82371 */
+ *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
+ *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
+ *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
+ *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
+
+ outb(0x11,0xA0);
+ outb(0x08,0xA1);
+ outb(0x02,0xA1);
+ outb(0x01,0xA1);
+ outb(0xFF,0xA1);
+
+ outb(0x11,0x20);
+ outb(0x00,0x21);
+ outb(0x04,0x21);
+ outb(0x01,0x21);
+ outb(0xFF,0x21);
+
+ /* Send -INTA pulses to clear any pending interrupts ...*/
+ *(vuip) PYXIS_IACK_SC;
+
+ /* Finish writing the 82C59A PIC Operation Control Words */
+ outb(0x20,0xA0);
+ outb(0x20,0x20);
+
+ /* Turn on the interrupt controller, the timer interrupt */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(0); /* enable timer */
+ enable_irq(2); /* enable 2nd PIC cascade */
+}
+
+
+/*
+ * For RUFFIAN, we do not want to make any modifications to the PCI
+ * setup. So just scan the busses.
+ */
+
+static void __init
+ruffian_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+}
+
+
+/*
+ * The DeskStation Ruffian motherboard firmware does not place
+ * the memory size in the PALimpure area. Therefore, we use
+ * the Bank Configuration Registers in PYXIS to obtain the size.
+ */
+static unsigned long __init
+ruffian_get_bank_size(unsigned long offset)
+{
+ unsigned long bank_addr, bank, ret = 0;
+
+ /* Valid offsets are: 0x800, 0x840 and 0x880
+ since Ruffian only uses three banks. */
+ bank_addr = (unsigned long)PYXIS_MCR + offset;
+ bank = *(vulp)bank_addr;
+
+ /* Check BANK_ENABLE */
+ if (bank & 0x01) {
+ static unsigned long size[] __initdata = {
+ 0x40000000UL, /* 0x00, 1G */
+ 0x20000000UL, /* 0x02, 512M */
+ 0x10000000UL, /* 0x04, 256M */
+ 0x08000000UL, /* 0x06, 128M */
+ 0x04000000UL, /* 0x08, 64M */
+ 0x02000000UL, /* 0x0a, 32M */
+ 0x01000000UL, /* 0x0c, 16M */
+ 0x00800000UL, /* 0x0e, 8M */
+ 0x80000000UL, /* 0x10, 2G */
+ };
+
+ bank = (bank & 0x1e) >> 1;
+ if (bank < sizeof(size)/sizeof(*size))
+ ret = size[bank];
+ }
+
+ return ret;
+}
+
+static void __init
+ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /* FIXME: What do we do with ruffian_get_bank_size above? */
+
+ pyxis_enable_errors();
+ if (!pyxis_srm_window_setup()) {
+ printk("ruffian_init_arch: Skipping window register rewrites."
+ "\n... Trust DeskStation firmware!\n");
+ }
+ pyxis_finish_init_arch();
+}
+
+
+static void
+ruffian_init_pit (void)
+{
+ /* Ruffian depends on the system timer established in MILO! */
+ request_region(0x70, 0x10, "timer");
+ init_pit_rest();
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_RUFFIAN)
+struct alpha_machine_vector ruffian_mv __initmv = {
+ vector_name: "Ruffian",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: RUFFIAN_PROBE_MASK,
+ update_irq_hw: ruffian_update_irq_hw,
+ ack_irq: ruffian_ack_irq,
+ device_interrupt: ruffian_device_interrupt,
+
+ init_arch: ruffian_init_arch,
+ init_irq: ruffian_init_irq,
+ init_pit: ruffian_init_pit,
+ pci_fixup: ruffian_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(ruffian)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_sable.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Sable and Sable-Gamma systems.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_t2.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * For SABLE, which is really baroque, we manage 40 IRQ's, but the
+ * hardware really only supports 24, not via normal ISA PIC,
+ * but cascaded custom 8259's, etc.
+ * 0-7 (char at 536)
+ * 8-15 (char at 53a)
+ * 16-23 (char at 53c)
+ */
+
+/* Note that the vector reported by the SRM PALcode corresponds to the
+ interrupt mask bits, but we have to manage via more normal IRQs. */
+
+static struct
+{
+ char irq_to_mask[40];
+ char mask_to_irq[40];
+ unsigned long shadow_mask;
+} sable_irq_swizzle = {
+ {
+ -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
+ -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
+ 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
+ },
+ {
+ 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
+ 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
+ 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
+ },
+ 0
+};
+
+
+static void
+sable_update_irq_hw(unsigned long irq, unsigned long unused_mask, int unmask_p)
+{
+ unsigned long bit, mask;
+
+ /* The "irq" argument is really the irq, but we need it to
+ be the mask bit number. Convert it now. */
+
+ irq = sable_irq_swizzle.irq_to_mask[irq];
+ bit = 1UL << irq;
+ mask = sable_irq_swizzle.shadow_mask | bit;
+ if (unmask_p)
+ mask &= ~bit;
+ sable_irq_swizzle.shadow_mask = mask;
+
+ /* The "irq" argument is now really the mask bit number. */
+ if (irq <= 7)
+ outb(mask, 0x537);
+ else if (irq <= 15)
+ outb(mask >> 8, 0x53b);
+ else
+ outb(mask >> 16, 0x53d);
+}
+
+static void
+sable_ack_irq(unsigned long irq)
+{
+ /* Note that the "irq" here is really the mask bit number */
+ switch (irq) {
+ case 0 ... 7:
+ outb(0xE0 | (irq - 0), 0x536);
+ outb(0xE0 | 1, 0x534); /* slave 0 */
+ break;
+ case 8 ... 15:
+ outb(0xE0 | (irq - 8), 0x53a);
+ outb(0xE0 | 3, 0x534); /* slave 1 */
+ break;
+ case 16 ... 24:
+ outb(0xE0 | (irq - 16), 0x53c);
+ outb(0xE0 | 4, 0x534); /* slave 2 */
+ break;
+ }
+}
+
+static void
+sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ /* Note that the vector reported by the SRM PALcode corresponds
+ to the interrupt mask bits, but we have to manage via more
+ normal IRQs. */
+
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ irq = sable_irq_swizzle.mask_to_irq[(ack)];
+#if 0
+ if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
+ irq == 14 || irq == 15)
+ printk("srm_device_interrupt: vector=0x%lx ack=0x%x"
+ " irq=0x%x\n", vector, ack, irq);
+#endif
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+sable_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ outb(alpha_irq_mask , 0x537); /* slave 0 */
+ outb(alpha_irq_mask >> 8, 0x53b); /* slave 1 */
+ outb(alpha_irq_mask >> 16, 0x53d); /* slave 2 */
+ outb(0x44, 0x535); /* enable cascades in master */
+}
+
+
+/*
+ * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
+ *
+ * Summary Registers (536/53a/53c):
+ * Bit Meaning
+ *-----------------
+ * 0 PCI slot 0
+ * 1 NCR810 (builtin)
+ * 2 TULIP (builtin)
+ * 3 mouse
+ * 4 PCI slot 1
+ * 5 PCI slot 2
+ * 6 keyboard
+ * 7 floppy
+ * 8 COM2
+ * 9 parallel port
+ *10 EISA irq 3
+ *11 EISA irq 4
+ *12 EISA irq 5
+ *13 EISA irq 6
+ *14 EISA irq 7
+ *15 COM1
+ *16 EISA irq 9
+ *17 EISA irq 10
+ *18 EISA irq 11
+ *19 EISA irq 12
+ *20 EISA irq 13
+ *21 EISA irq 14
+ *22 NC
+ *23 IIC
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 0 TULIP
+ * 1 SCSI
+ * 2 PCI-EISA bridge
+ * 3 none
+ * 4 none
+ * 5 none
+ * 6 PCI on board slot 0
+ * 7 PCI on board slot 1
+ * 8 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+/*
+ * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
+ * with the values in the irq swizzling tables above.
+ */
+
+static int __init
+sable_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[9][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
+ { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
+ { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
+ { -1, -1, -1, -1, -1}, /* IdSel 3, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 4, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 5, none */
+ { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
+ { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
+ { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
+ };
+ const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+void __init
+sable_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(sable_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vectors
+ *
+ * In order that T2_HAE_ADDRESS should be a constant, we play
+ * these games with GAMMA_BIAS.
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA)
+#undef GAMMA_BIAS
+#define GAMMA_BIAS 0
+struct alpha_machine_vector sable_mv __initmv = {
+ vector_name: "Sable",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_T2_IO,
+ DO_T2_BUS,
+ machine_check: t2_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sable_update_irq_hw,
+ ack_irq: sable_ack_irq,
+ device_interrupt: sable_srm_device_interrupt,
+
+ init_arch: t2_init_arch,
+ init_irq: sable_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sable_pci_fixup,
+ kill_arch: generic_kill_arch,
+
+ sys: { t2: {
+ gamma_bias: 0
+ } }
+};
+ALIAS_MV(sable)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA)
+#undef GAMMA_BIAS
+#define GAMMA_BIAS _GAMMA_BIAS
+struct alpha_machine_vector sable_gamma_mv __initmv = {
+ vector_name: "Sable-Gamma",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_T2_IO,
+ DO_T2_BUS,
+ machine_check: t2_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sable_update_irq_hw,
+ ack_irq: sable_ack_irq,
+ device_interrupt: sable_srm_device_interrupt,
+
+ init_arch: t2_init_arch,
+ init_irq: sable_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sable_pci_fixup,
+ kill_arch: generic_kill_arch,
+
+ sys: { t2: {
+ gamma_bias: _GAMMA_BIAS
+ } }
+};
+ALIAS_MV(sable_gamma)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_sio.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code for all boards that route the PCI interrupts through the SIO
+ * PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB),
+ * Kenetics's Platform 2000, Avanti (AlphaStation), XL, and AlphaBook1.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/compiler.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_lca.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+static void
+sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void __init
+sio_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ enable_irq(2); /* enable cascade */
+}
+
+static inline void __init
+xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /*
+ * Set up the PCI->physical memory translation windows. For
+ * the XL we *must* use both windows, in order to maximize the
+ * amount of physical memory that can be used to DMA from the
+ * ISA bus, and still allow PCI bus devices access to all of
+ * host memory.
+ *
+ * See <asm/apecs.h> for window bases and sizes.
+ *
+ * This restriction due to the true XL motherboards' 82379AB SIO
+ * PCI<->ISA bridge chip which passes only 27 bits of address...
+ */
+
+ *(vuip)APECS_IOC_PB1R = 1<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+
+ *(vuip)APECS_IOC_PB2R = 1<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB2R = 0;
+
+ /*
+ * Finally, clear the HAXR2 register, which gets used for PCI
+ * Config Space accesses. That is the way we want to use it,
+ * and we do not want to depend on what ARC or SRM might have
+ * left behind...
+ */
+
+ *(vuip)APECS_IOC_HAXR2 = 0; mb();
+}
+
+static inline void __init
+alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /* The AlphaBook1 has LCD video fixed at 800x600,
+ 37 rows and 100 cols. */
+ screen_info.orig_y = 37;
+ screen_info.orig_video_cols = 100;
+ screen_info.orig_video_lines = 37;
+
+ lca_init_arch(mem_start, mem_end);
+}
+
+
+/*
+ * sio_route_tab selects irq routing in PCI/ISA bridge so that:
+ * PIRQ0 -> irq 15
+ * PIRQ1 -> irq 9
+ * PIRQ2 -> irq 10
+ * PIRQ3 -> irq 11
+ *
+ * This probably ought to be configurable via MILO. For
+ * example, sound boards seem to like using IRQ 9.
+ */
+static unsigned long sio_route_tab __initdata = 0;
+
+static void __init
+sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin),
+ unsigned long new_route_tab)
+{
+ unsigned int route_tab;
+
+ /* Examine or update the PCI routing table. */
+ pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab);
+
+ sio_route_tab = route_tab;
+ if (PCI_MODIFY) {
+ sio_route_tab = new_route_tab;
+ pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
+ new_route_tab);
+ }
+
+ /* Update all the IRQs. */
+ common_pci_fixup(map_irq, common_swizzle);
+}
+
+static unsigned int __init
+sio_collect_irq_levels(void)
+{
+ unsigned int level_bits = 0;
+ struct pci_dev *dev;
+
+ /* Iterate through the devices, collecting IRQ levels. */
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
+ (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
+ continue;
+
+ if (dev->irq)
+ level_bits |= (1 << dev->irq);
+ }
+ return level_bits;
+}
+
+static void __init
+sio_fixup_irq_levels(unsigned int level_bits)
+{
+ unsigned int old_level_bits;
+
+ /*
+ * Now, make all PCI interrupts level sensitive. Notice:
+ * these registers must be accessed byte-wise. inw()/outw()
+ * don't work.
+ *
+ * Make sure to turn off any level bits set for IRQs 9,10,11,15,
+ * so that the only bits getting set are for devices actually found.
+ * Note that we do preserve the remainder of the bits, which we hope
+ * will be set correctly by ARC/SRM.
+ *
+ * Note: we at least preserve any level-set bits on AlphaBook1
+ */
+ old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
+
+ level_bits |= (old_level_bits & 0x71ff);
+
+ outb((level_bits >> 0) & 0xff, 0x4d0);
+ outb((level_bits >> 8) & 0xff, 0x4d1);
+}
+
+static inline int __init
+noname_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ /*
+ * The Noname board has 5 PCI slots with each of the 4
+ * interrupt pins routed to different pins on the PCI/ISA
+ * bridge (PIRQ0-PIRQ3). The table below is based on
+ * information available at:
+ *
+ * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
+ *
+ * I have no information on the Avanti interrupt routing, but
+ * the routing seems to be identical to the Noname except
+ * that the Avanti has an additional slot whose routing I'm
+ * unsure of.
+ *
+ * pirq_tab[0] is a fake entry to deal with old PCI boards
+ * that have the interrupt pin number hardwired to 0 (meaning
+ * that they use the default INTA line, if they are interrupt
+ * driven at all).
+ */
+ static char irq_tab[][5] __initlocaldata = {
+ /*INT A B C D */
+ { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
+ {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
+ { 2, 2, -1, -1, -1}, /* idsel 8 (Hack: slot closest ISA) */
+ {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
+ {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+ { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
+ { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
+ { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
+ { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
+ };
+ const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP, tmp;
+ tmp = __kernel_extbl(sio_route_tab, irq);
+ return irq >= 0 ? tmp : -1;
+}
+
+static inline void __init
+noname_pci_fixup(void)
+{
+ /*
+ * For UDB, the only available PCI slot must not map to IRQ 9,
+ * since that's the builtin MSS sound chip. That PCI slot
+ * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+ * instead.
+ *
+ * Unfortunately we have to do this for NONAME as well, since
+ * they are co-indicated when the platform type "Noname" is
+ * selected... :-(
+ */
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a0f09);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+avanti_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+xl_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline int __init
+p2k_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[][5] __initlocaldata = {
+ /*INT A B C D */
+ { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
+ {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
+ { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
+ { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
+ {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+ {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
+ { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
+ };
+ const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP, tmp;
+ tmp = __kernel_extbl(sio_route_tab, irq);
+ return irq >= 0 ? tmp : -1;
+}
+
+static inline void __init
+p2k_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(p2k_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+alphabook1_pci_fixup(void)
+{
+ struct pci_dev *dev;
+ unsigned char orig, config;
+
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+
+ /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */
+ sio_pci_fixup(noname_map_irq, 0x0e0f0a0a);
+
+ /*
+ * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
+ * is sensitive to PCI bus bursts, so we must DISABLE
+ * burst mode for the NCR 8xx SCSI... :-(
+ *
+ * Note that the NCR810 SCSI driver must preserve the
+ * setting of the bit in order for this to work. At the
+ * moment (2.0.29), ncr53c8xx.c does NOT do this, but
+ * 53c7,8xx.c DOES.
+ */
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->vendor == PCI_VENDOR_ID_NCR &&
+ (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C815 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C820 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C825)) {
+ unsigned int io_port;
+ unsigned char ctest4;
+
+ pcibios_read_config_dword(dev->bus->number,
+ dev->devfn,
+ PCI_BASE_ADDRESS_0,
+ &io_port);
+ io_port &= PCI_BASE_ADDRESS_IO_MASK;
+ ctest4 = inb(io_port+0x21);
+ if (!(ctest4 & 0x80)) {
+ printk("AlphaBook1 NCR init: setting"
+ " burst disable\n");
+ outb(ctest4 | 0x80, io_port+0x21);
+ }
+ }
+ }
+
+ /* Do not set *ANY* level triggers for AlphaBook1. */
+ sio_fixup_irq_levels(0);
+
+ /* Make sure that register PR1 indicates 1Mb mem */
+ outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
+ outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
+ outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
+ if ((config & 0xc0) != 0xc0) {
+ printk("AlphaBook1 VGA init: setting 1Mb memory\n");
+ config |= 0xc0;
+ outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
+ }
+ outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1)
+struct alpha_machine_vector alphabook1_mv __initmv = {
+ vector_name: "AlphaBook1",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: alphabook1_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphabook1_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(alphabook1)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI)
+struct alpha_machine_vector avanti_mv __initmv = {
+ vector_name: "Avanti",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: avanti_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(avanti)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME)
+struct alpha_machine_vector noname_mv __initmv = {
+ vector_name: "Noname",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: srm_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noname_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noname)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K)
+struct alpha_machine_vector p2k_mv __initmv = {
+ vector_name: "Platform2000",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: P2K_PROBE_MASK,
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: srm_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: p2k_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(p2k)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL)
+struct alpha_machine_vector xl_mv __initmv = {
+ vector_name: "XL",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ BUS(apecs_xl),
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: xl_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: xl_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(xl)
+#endif
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_sx164.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the SX164 (PCA56+PYXIS).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+sx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & ~0x000000000000003bUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+sx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ if (unmask_p)
+ cserve_ena(irq - 16);
+ else
+ cserve_dis(irq - 16);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+sx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld, tmp;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /*
+ * For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7)
+ * then all the PCI slots/INTXs (8-23)
+ */
+ /* Maybe HALT should only be used for SRM console boots? */
+ pld &= 0x0000000000ffffc0UL;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ isa_device_interrupt(vector, regs);
+ } else if (i == 6) {
+ continue;
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ tmp = *(vulp)PYXIS_INT_REQ;
+ }
+ restore_flags(flags);
+}
+
+static void
+sx164_init_irq(void)
+{
+ outb(0, DMA1_RESET_REG);
+ outb(0, DMA2_RESET_REG);
+
+ if (alpha_using_srm) {
+ alpha_mv.update_irq_hw = sx164_srm_update_irq_hw;
+ alpha_mv.device_interrupt = srm_device_interrupt;
+ }
+ else {
+ /* Note invert on MASK bits. */
+ *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16);
+ mb();
+ *(vulp)PYXIS_INT_MASK;
+ }
+
+ enable_irq(16 + 6); /* enable timer */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ PYXIS_INT_REQ:
+ * Bit Meaning
+ * 0 RSVD
+ * 1 NMI
+ * 2 Halt/Reset switch
+ * 3 MBZ
+ * 4 RAZ
+ * 5 RAZ
+ * 6 Interval timer (RTC)
+ * 7 PCI-ISA Bridge
+ * 8 Interrupt Line A from slot 3
+ * 9 Interrupt Line A from slot 2
+ *10 Interrupt Line A from slot 1
+ *11 Interrupt Line A from slot 0
+ *12 Interrupt Line B from slot 3
+ *13 Interrupt Line B from slot 2
+ *14 Interrupt Line B from slot 1
+ *15 Interrupt line B from slot 0
+ *16 Interrupt Line C from slot 3
+ *17 Interrupt Line C from slot 2
+ *18 Interrupt Line C from slot 1
+ *19 Interrupt Line C from slot 0
+ *20 Interrupt Line D from slot 3
+ *21 Interrupt Line D from slot 2
+ *22 Interrupt Line D from slot 1
+ *23 Interrupt Line D from slot 0
+ *
+ * IdSel
+ * 5 32 bit PCI option slot 2
+ * 6 64 bit PCI option slot 0
+ * 7 64 bit PCI option slot 1
+ * 8 Cypress I/O
+ * 9 32 bit PCI option slot 3
+ *
+ */
+
+static int __init
+sx164_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
+ { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
+ { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
+ { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+void __init
+sx164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(sx164_map_irq, common_swizzle);
+ SMC669_Init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector sx164_mv __initmv = {
+ vector_name: "SX164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sx164_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: sx164_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: sx164_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sx164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(sx164)
--- /dev/null
+/*
+ * linux/arch/alpha/kernel/sys_takara.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the TAKARA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * WARNING WARNING WARNING
+ *
+ * This port is missing an update_irq_hw implementation.
+ */
+
+static void
+takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned intstatus;
+
+ save_and_cli(flags);
+
+ /*
+ * The PALcode will have passed us vectors 0x800 or 0x810,
+ * which are fairly arbitrary values and serve only to tell
+ * us whether an interrupt has come in on IRQ0 or IRQ1. If
+ * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
+ * probably ISA, but PCI interrupts can come through IRQ0
+ * as well if the interrupt controller isn't in accelerated
+ * mode.
+ *
+ * OTOH, the accelerator thing doesn't seem to be working
+ * overly well, so what we'll do instead is try directly
+ * examining the Master Interrupt Register to see if it's a
+ * PCI interrupt, and if _not_ then we'll pass it on to the
+ * ISA handler.
+ */
+
+ intstatus = inw(0x500) & 15;
+ if (intstatus) {
+ /*
+ * This is a PCI interrupt. Check each bit and
+ * despatch an interrupt if it's set.
+ */
+
+ if (intstatus & 8) handle_irq(16+3, 16+3, regs);
+ if (intstatus & 4) handle_irq(16+2, 16+2, regs);
+ if (intstatus & 2) handle_irq(16+1, 16+1, regs);
+ if (intstatus & 1) handle_irq(16+0, 16+0, regs);
+ } else
+ isa_device_interrupt (vector, regs);
+
+ restore_flags(flags);
+}
+
+static void __init
+takara_init_irq(void)
+{
+ unsigned int ctlreg;
+
+ STANDARD_INIT_IRQ_PROLOG;
+
+ ctlreg = inl(0x500);
+ ctlreg &= ~0x8000; /* return to non-accelerated mode */
+ outw(ctlreg >> 16, 0x502);
+ outw(ctlreg & 0xFFFF, 0x500);
+ ctlreg = 0x05107c00; /* enable the PCI interrupt register */
+ outw(ctlreg >> 16, 0x502);
+ outw(ctlreg & 0xFFFF, 0x500);
+ enable_irq(2);
+}
+
+
+/*
+ * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
+ * 19, and 18 respectively, in the default configuration. They can
+ * also be jumpered to slots 8, 7, and 6 respectively, which is fun
+ * because the SIO ISA bridge can also be slot 7. However, the SIO
+ * doesn't explicitly generate PCI-type interrupts, so we can
+ * assign it whatever the hell IRQ we like and it doesn't matter.
+ */
+
+static int __init
+takara_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[15][5] __initlocaldata = {
+ { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
+ { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
+ { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
+ { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
+ { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
+ };
+ const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+takara_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(takara_map_irq, common_swizzle);
+ enable_ide(0x26e);
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector takara_mv __initmv = {
+ vector_name: "Takara",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 20,
+ irq_probe_mask: _PROBE_MASK(20),
+ update_irq_hw: NULL,
+ ack_irq: generic_ack_irq,
+ device_interrupt: takara_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: takara_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: takara_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(takara)
+++ /dev/null
-/*
- * Code common to all T2 chips.
- *
- * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
- * December 1996.
- *
- * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
- *
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.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>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * Machine check reasons. Defined according to PALcode sources
- * (osf.h and platform.h).
- */
-#define MCHK_K_TPERR 0x0080
-#define MCHK_K_TCPERR 0x0082
-#define MCHK_K_HERR 0x0084
-#define MCHK_K_ECC_C 0x0086
-#define MCHK_K_ECC_NC 0x0088
-#define MCHK_K_OS_BUGCHECK 0x008A
-#define MCHK_K_PAL_BUGCHECK 0x0090
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef DEBUG_CONF
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#ifdef DEBUG_MCHECK
-# define DBGMC(args) printk args
-#else
-# define DBGMC(args)
-#endif
-
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
-static volatile unsigned int T2_mcheck_expected[NR_CPUS];
-static volatile unsigned int T2_mcheck_taken[NR_CPUS];
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
-unsigned int T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
-unsigned long t2_sm_base;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the T2_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, dfn=0x%x, where=0x%x,"
- " addr=0x%lx, type1=0x%x)\n",
- bus, device_fn, where, pci_addr, type1));
-
- if (bus == 0) {
- int device = device_fn >> 3;
-
- /* type 0 configuration cycle: */
-
- if (device > 8) {
- DBG(("mk_conf_addr: device (%d)>20, returning -1\n",
- device));
- return -1;
- }
-
- *type1 = 0;
- addr = (0x0800L << device) | ((device_fn & 7) << 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, cpu;
- unsigned long t2_cfg = 0; /* to keep gcc quiet */
-
- cpu = smp_processor_id();
-
- save_flags(flags); /* avoid getting hit by machine check */
- cli();
-
- DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
-
-#if 0
- /* reset status register to avoid losing errors: */
- stat0 = *(vulp)T2_IOCSR;
- *(vulp)T2_IOCSR = stat0;
- mb();
- DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
-#endif
- /* if Type1 access, must set T2 CFG */
- if (type1) {
- t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
- *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
- mb();
- DBG(("conf_read: TYPE1 access\n"));
- }
- mb();
- draina();
-
- T2_mcheck_expected[cpu] = 1;
- T2_mcheck_taken[cpu] = 0;
- mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
- if (T2_mcheck_taken[cpu]) {
- T2_mcheck_taken[cpu] = 0;
- value = 0xffffffffU;
- mb();
- }
- T2_mcheck_expected[cpu] = 0;
- mb();
-
- /* if Type1 access, must reset T2 CFG so normal IO space ops work */
- if (type1) {
- *(vulp)T2_HAE_3 = t2_cfg;
- 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, cpu;
- unsigned long t2_cfg = 0; /* to keep gcc quiet */
-
- cpu = smp_processor_id();
-
- save_flags(flags); /* avoid getting hit by machine check */
- cli();
-
-#if 0
- /* reset status register to avoid losing errors: */
- stat0 = *(vulp)T2_IOCSR;
- *(vulp)T2_IOCSR = stat0;
- mb();
- DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
-#endif
- /* if Type1 access, must set T2 CFG */
- if (type1) {
- t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
- *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
- mb();
- DBG(("conf_write: TYPE1 access\n"));
- }
- mb();
- draina();
-
- T2_mcheck_expected[cpu] = 1;
- mb();
- /* access configuration space: */
- *(vuip)addr = value;
- mb();
- mb(); /* magic */
- T2_mcheck_expected[cpu] = 0;
- mb();
-
- /* if Type1 access, must reset T2 CFG so normal IO space ops work */
- if (type1) {
- *(vulp)T2_HAE_3 = t2_cfg;
- 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 = T2_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 = T2_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 = T2_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 = T2_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 = T2_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 = T2_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 t2_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned long t2_err;
- unsigned int i;
-
- for (i = 0; i < NR_CPUS; i++) {
- T2_mcheck_expected[i] = 0;
- T2_mcheck_taken[i] = 0;
- }
-
-#if 0
- /*
- * Set up error reporting.
- */
- t2_err = *(vulp)T2_IOCSR ;
- t2_err |= (0x1 << 7) ; /* master abort */
- *(vulp)T2_IOCSR = t2_err ;
- mb() ;
-#endif
-
- printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE);
-#if 0
- printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
- *(vulp)T2_WBASE1,
- *(vulp)T2_WMASK1,
- *(vulp)T2_TBASE1);
- printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
- *(vulp)T2_WBASE2,
- *(vulp)T2_WMASK2,
- *(vulp)T2_TBASE2);
-#endif
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 1 for enabled and mapped to 0 */
- if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) &&
- (*(vulp)T2_TBASE1 == 0))
- {
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
-/* DISABLE window 2!! ?? */
-#if 1
- printk("t2_init: using Window 1 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE1,
- *(vulp)T2_WMASK1,
- *(vulp)T2_TBASE1);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) &&
- (*(vulp)T2_TBASE2 == 0))
- {
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
-/* DISABLE window 1!! ?? */
-#if 1
- printk("t2_init: using Window 2 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE2,
- *(vulp)T2_WMASK2,
- *(vulp)T2_TBASE2);
-#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
-
- /* WARNING!! must correspond to the DMA_WIN params!!! */
- *(vulp)T2_WBASE1 = 0x400807ffU;
- *(vulp)T2_WMASK1 = 0x3ff00000U;
- *(vulp)T2_TBASE1 = 0;
-
- *(vulp)T2_WBASE2 = 0x0;
- *(vulp)T2_HBASE = 0x0;
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("T2_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- /*
- * Finally, clear the T2_HAE_3 register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
- unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
- unsigned long t2_hae_2 = *(vulp)T2_HAE_2;
- unsigned long t2_hae_3 = *(vulp)T2_HAE_3;
- unsigned long t2_hae_4 = *(vulp)T2_HAE_4;
-#if 1
- printk("T2_init: HAE1 was 0x%lx\n", t2_hae_1);
- printk("T2_init: HAE2 was 0x%lx\n", t2_hae_2);
- printk("T2_init: HAE3 was 0x%lx\n", t2_hae_3);
- printk("T2_init: HAE4 was 0x%lx\n", t2_hae_4);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * see include/asm-alpha/t2.h for the SPARSE mem read/write
- */
- t2_sm_base = (t2_hae_1 << 27) & 0xf8000000UL;
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in .h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = t2_hae_1;
-#else /* SRM_SETUP */
- *(vulp)T2_HAE_1 = 0; mb();
- *(vulp)T2_HAE_2 = 0; mb();
- *(vulp)T2_HAE_3 = 0; mb();
-#if 0
- *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
-#endif
-#endif /* SRM_SETUP */
- }
-
- return mem_start;
-}
-
-#define SIC_SEIC (1UL << 33) /* System Event Clear */
-
-static struct sable_cpu_csr *sable_cpu_regs[4] = {
- (struct sable_cpu_csr *)CPU0_BASE,
- (struct sable_cpu_csr *)CPU1_BASE,
- (struct sable_cpu_csr *)CPU2_BASE,
- (struct sable_cpu_csr *)CPU3_BASE,
-};
-
-int t2_clear_errors(void)
-{
- unsigned int cpu = smp_processor_id();
-
- DBGMC(("???????? t2_clear_errors\n"));
-
- sable_cpu_regs[cpu]->sic &= ~SIC_SEIC;
-
- /*
- * clear CPU errors
- */
- sable_cpu_regs[cpu]->bcce |= sable_cpu_regs[cpu]->bcce;
- sable_cpu_regs[cpu]->cbe |= sable_cpu_regs[cpu]->cbe;
- sable_cpu_regs[cpu]->bcue |= sable_cpu_regs[cpu]->bcue;
- sable_cpu_regs[cpu]->dter |= sable_cpu_regs[cpu]->dter;
-
- *(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
- *(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
-
- mb();
- mb(); /* magic */
- return 0;
-}
-
-void t2_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- struct el_t2_logout_header *mchk_header;
- struct el_t2_procdata_mcheck *mchk_procdata;
- struct el_t2_sysdata_mcheck *mchk_sysdata;
- unsigned long * ptr;
- const char * reason;
- char buf[128];
- long i;
- unsigned int cpu = smp_processor_id();
-
- DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
-
- mchk_header = (struct el_t2_logout_header *)la_ptr;
-
- DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n",
- mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset));
-
- mchk_sysdata = (struct el_t2_sysdata_mcheck *)
- (la_ptr + mchk_header->elfl_sysoffset);
- mchk_procdata = (struct el_t2_procdata_mcheck *)
- (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
-
- DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
- mchk_header->elfl_sysoffset));
- DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu]));
-
-#ifdef DEBUG_DUMP
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long),
- ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_DUMP */
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (T2_mcheck_expected[cpu]) {
- DBGMC(("T2 machine check expected\n"));
- T2_mcheck_taken[cpu] = 1;
- t2_clear_errors();
- T2_mcheck_expected[cpu] = 0;
- mb();
- mb(); /* magic */
- wrmces(rdmces()|1);/* ??? */
- draina();
- return;
- }
-
- switch ((unsigned int) mchk_header->elfl_error_type) {
- case MCHK_K_TPERR: reason = "tag parity error"; break;
- case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "generic hard error"; break;
- case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
- case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
- case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
- case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break;
- case 0x96: reason = "i-cache read retryable error"; break;
- case 0x98: reason = "processor detected hard error"; break;
-
- /* System specific (these are for Alcor, at least): */
- case 0x203: reason = "system detected uncorrectable ECC error"; break;
- case 0x205: reason = "parity error detected by T2"; break;
- case 0x207: reason = "non-existent memory error"; break;
- case 0x209: reason = "PCI SERR detected"; break;
- case 0x20b: reason = "PCI data parity error detected"; break;
- case 0x20d: reason = "PCI address parity error detected"; break;
- case 0x20f: reason = "PCI master abort error"; break;
- case 0x211: reason = "PCI target abort error"; break;
- case 0x213: reason = "scatter/gather PTE invalid error"; break;
- case 0x215: reason = "flash ROM write error"; break;
- case 0x217: reason = "IOA timeout detected"; break;
- case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
- case 0x21b: reason = "EISA fail-safe timer timeout"; break;
- case 0x21d: reason = "EISA bus time-out"; break;
- case 0x21f: reason = "EISA software generated NMI"; break;
- case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
- default:
- sprintf(buf, "reason for machine-check unknown (0x%x)",
- (unsigned int) mchk_header->elfl_error_type);
- reason = buf;
- break;
- }
- wrmces(rdmces()|1); /* reset machine check pending flag */
- mb();
-
- printk(KERN_CRIT " T2 machine check: %s%s\n",
- reason, mchk_header->elfl_retry ? " (retryable)" : "");
-
- /* dump the logout area to give all info: */
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-}
#include <asm/unaligned.h>
#include <asm/sysinfo.h>
+#include "proto.h"
-static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
+static void
+dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
regs->pc, regs->r26, regs->ps);
printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
}
-static void dik_show_code(unsigned int *pc)
+static void
+dik_show_code(unsigned int *pc)
{
long i;
printk("\n");
}
-static void dik_show_trace(unsigned long *sp)
+static void
+dik_show_trace(unsigned long *sp)
{
long i = 0;
printk("Trace:");
printk("\n");
}
-void die_if_kernel(char * str, struct pt_regs *regs, long err,
- unsigned long *r9_15)
+void
+die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
{
if (regs->ps & 8)
return;
}
#ifndef CONFIG_MATHEMU
-static long dummy_alpha_fp_emul_imprecise(struct pt_regs *r, unsigned long wm)
-{
- return 0;
-}
-
+static long dummy_emul() { return 0; }
long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
- = dummy_alpha_fp_emul_imprecise;
+ = (void *)dummy_emul;
+long (*alpha_fp_emul) (unsigned long pc)
+ = (void *)dummy_emul;
#else
long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
+long alpha_fp_emul (unsigned long pc);
#endif
-asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
- unsigned long a2, unsigned long a3,
- unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage void
+do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
if ((summary & 1)) {
/*
}
lock_kernel();
+#if 0
printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
current->comm, regs.pc, summary, write_mask);
+#endif
die_if_kernel("Arithmetic fault", ®s, 0, 0);
force_sig(SIGFPE, current);
unlock_kernel();
case 4: /* opDEC */
#ifdef CONFIG_ALPHA_NEED_ROUNDING_EMULATION
{
- extern long alpha_fp_emul (unsigned long pc);
unsigned int opcode;
/* get opcode of faulting instruction: */
#define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
-asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct allregs regs)
+asmlinkage void
+do_entUna(void * va, unsigned long opcode, unsigned long reg,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct allregs regs)
{
long error, tmp1, tmp2, tmp3, tmp4;
unsigned long pc = regs.pc - 4;
* needs to be remapped to preserve non-finite values
* (infinities, not-a-numbers, denormals).
*/
-static inline unsigned long s_mem_to_reg (unsigned long s_mem)
+static inline unsigned long
+s_mem_to_reg (unsigned long s_mem)
{
unsigned long frac = (s_mem >> 0) & 0x7fffff;
unsigned long sign = (s_mem >> 31) & 0x1;
* Convert an s-floating point value in register format to the
* corresponding value in memory format.
*/
-static inline unsigned long s_reg_to_mem (unsigned long s_reg)
+static inline unsigned long
+s_reg_to_mem (unsigned long s_reg)
{
return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
}
#undef R
-asmlinkage void do_entUnaUser(void * va, unsigned long opcode,
- unsigned long reg, struct pt_regs *regs)
+asmlinkage void
+do_entUnaUser(void * va, unsigned long opcode,
+ unsigned long reg, struct pt_regs *regs)
{
- extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
- extern unsigned long alpha_read_fp_reg (unsigned long reg);
-
static int cnt = 0;
static long last_time = 0;
/*
* Unimplemented system calls.
*/
-asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1,
- unsigned long a2, unsigned long a3,
- unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage long
+alpha_ni_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
/* We only get here for OSF system calls, minus #112;
the rest go to sys_ni_syscall. */
return -ENOSYS;
}
-extern asmlinkage void entMM(void);
-extern asmlinkage void entIF(void);
-extern asmlinkage void entArith(void);
-extern asmlinkage void entUna(void);
-extern asmlinkage void entSys(void);
-
-register unsigned long gptr __asm__("$29");
-
-void trap_init(void)
+void
+trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
+ register unsigned long gptr __asm__("$29");
wrkgp(gptr);
wrent(entArith, 1);
+++ /dev/null
-/*
- * Code common to all TSUNAMI chips.
- *
- * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.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>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the I/O controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef CONFIG_ALPHA_TSUNAMI
-
-#ifdef DEBUG
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
-static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
-static unsigned int TSUNAMI_jd[NR_CPUS];
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
-unsigned int TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address
- * 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.
- *
- * Note that all config space accesses use Type 1 address format.
- *
- * Note also that type 1 is determined by non-zero bus 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) {
- *type1 = 0;
- } 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;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned char result;
-
- *value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned short result;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned int result;
-
- *value = 0xffffffff;
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldl %0,%1"
- : "=r" (result)
- : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stl %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-unsigned long tsunami_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned long tsunami_err;
- unsigned int i;
-
-#if 0
-printk("tsunami_init: CChip registers:\n");
-printk("tsunami_init: CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC);
-printk("tsunami_init: CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR);
-printk("tsunami_init: CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC);
-printk("tsunami_init: CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0);
-printk("tsunami_init: CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1);
-printk("tsunami_init: CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0);
-printk("tsunami_init: CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1);
-printk("tsunami_init: CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR);
-
-printk("tsunami_init: DChip registers:\n");
-printk("tsunami_init: CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC);
-printk("tsunami_init: CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR);
-printk("tsunami_init: CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV);
-
-printk("tsunami_init: PChip registers:\n");
-printk("tsunami_init: PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0);
-printk("tsunami_init: PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1);
-printk("tsunami_init: PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2);
-printk("tsunami_init: PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3);
-printk("tsunami_init: PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0);
-printk("tsunami_init: PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1);
-printk("tsunami_init: PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2);
-printk("tsunami_init: PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3);
-printk("tsunami_init: PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0);
-printk("tsunami_init: PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1);
-printk("tsunami_init: PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2);
-printk("tsunami_init: PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3);
-
-printk("tsunami_init: PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL);
-printk("tsunami_init: PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT);
-printk("tsunami_init: PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR);
-printk("tsunami_init: PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK);
-
-#endif
-
- for (i = 0; i < NR_CPUS; i++) {
- TSUNAMI_mcheck_expected[i] = 0;
- TSUNAMI_mcheck_taken[i] = 0;
- }
-#ifdef NOT_YET
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
- tsunami_err &= ~20;
- *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err;
- mb();
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
-
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
- tsunami_err |= 0x40; /* master/target abort */
- *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ;
- mb() ;
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
-#endif /* NOT_YET */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 0 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA0,
- *(vulp)TSUNAMI_PCHIP0_WSM0,
- *(vulp)TSUNAMI_PCHIP0_TBA0);
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U))
-{
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 1 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA1,
- *(vulp)TSUNAMI_PCHIP0_WSM1,
- *(vulp)TSUNAMI_PCHIP0_TBA1);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TSB2 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 2 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA2,
- *(vulp)TSUNAMI_PCHIP0_WSM2,
- *(vulp)TSUNAMI_PCHIP0_TSB2);
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 3 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA3,
- *(vulp)TSUNAMI_PCHIP0_WSM3,
- *(vulp)TSUNAMI_PCHIP0_TBA3);
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * 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.
- */
-
- *(vulp)TSUNAMI_PCHIP0_WSBA0 = 1L | (TSUNAMI_DMA_WIN_BASE & 0xfff00000U);
- *(vulp)TSUNAMI_PCHIP0_WSM0 = (TSUNAMI_DMA_WIN_SIZE - 1) & 0xfff00000UL;
- *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL;
-
- *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL;
- *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL;
- *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL;
- mb();
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("TSUNAMI_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- return mem_start;
-}
-
-int tsunami_pci_clr_err(void)
-{
- unsigned int cpu = smp_processor_id();
-
- TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
- DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n", TSUNAMI_jd[cpu]));
- *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb();
- TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
- return 0;
-}
-
-void tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
-#if 1
- printk("TSUNAMI machine check ignored\n") ;
-#else
- struct el_common *mchk_header;
- struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
- unsigned int cpu = smp_processor_id();
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata =
- (struct el_TSUNAMI_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t 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_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- 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_MCHECK_DUMP */
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (TSUNAMI_mcheck_expected[cpu]) {
- DBG(("TSUNAMI machine check expected\n"));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("TSUNAMI machine check NOT expected\n") ;
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t 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));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
-#endif
-}
-
-#endif /* CONFIG_ALPHA_TSUNAMI */
strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
strchr.o strrchr.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o
+ csum_ipv6_magic.o strcasecmp.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
#include <linux/types.h>
#include <asm/io.h>
-/*
- * Jensen has a separate "local" and "bus" IO space for
- * byte-wide IO.
- */
-#ifdef __is_local
-
-unsigned int _bus_inb(unsigned long addr)
-{
- return __bus_inb(addr);
-}
-
-void _bus_outb(unsigned char b, unsigned long addr)
-{
- __bus_outb(b, addr);
-}
-#endif
-
unsigned int _inb(unsigned long addr)
{
return __inb(addr);
/*
* "memset" on IO memory space.
- * This needs to be optimized.
*/
void _memset_c_io(unsigned long to, unsigned long c, long count)
{
+ /* Handle any initial odd byte */
if (count > 0 && (to & 1)) {
writeb(c, to);
to++;
count--;
}
+
+ /* Handle any initial odd halfword */
if (count >= 2 && (to & 2)) {
writew(c, to);
to += 2;
count -= 2;
}
+
+ /* Handle any initial odd word */
if (count >= 4 && (to & 4)) {
writel(c, to);
to += 4;
count -= 4;
}
- if ((to & 7) == 0) {
- count -= 8;
- while (count >= 0) {
+
+ /* Handle all full-sized quadwords: we're aligned (or have a small count) */
+ count -= 8;
+ if (count >= 0) {
+ do {
writeq(c, to);
to += 8;
count -= 8;
- }
- count += 8;
+ } while (count >= 0);
}
- if (count >= 4 && (to & 4)) {
+ count += 8;
+
+ /* The tail is word-aligned if we still have count >= 4 */
+ if (count >= 4) {
writel(c, to);
to += 4;
count -= 4;
}
- if (count >= 2 && (to & 2)) {
+
+ /* The tail is half-word aligned if we have count >= 2 */
+ if (count >= 2) {
writew(c, to);
to += 2;
count -= 2;
}
- while (count > 0) {
+
+ /* And finally, one last byte.. */
+ if (count) {
writeb(c, to);
- count--;
- to++;
}
}
--- /dev/null
+/*
+ * linux/arch/alpha/lib/strcasecmp.c
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale. Since this is used in
+ only one place, on strings known to contain only 7 bit ASCII, this
+ is ok. */
+
+int strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ } while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
MODULE_DESCRIPTION("FP Software completion module");
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
-static long (*save_emul)(struct pt_regs *, unsigned long);
+extern long (*alpha_fp_emul) (unsigned long pc);
+
+static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
+static long (*save_emul) (unsigned long pc);
+
long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
+long do_alpha_fp_emul(unsigned long);
int init_module(void)
{
- save_emul = alpha_fp_emul_imprecise;
+ save_emul_imprecise = alpha_fp_emul_imprecise;
+ save_emul = alpha_fp_emul;
alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
+ alpha_fp_emul = do_alpha_fp_emul;
return 0;
}
void cleanup_module(void)
{
- alpha_fp_emul_imprecise = save_emul;
+ alpha_fp_emul_imprecise = save_emul_imprecise;
+ alpha_fp_emul = save_emul;
}
-#undef alpha_fp_emul_imprecise
-#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+#undef alpha_fp_emul_imprecise
+#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+#undef alpha_fp_emul
+#define alpha_fp_emul do_alpha_fp_emul
#endif /* MODULE */
unsigned long va, vb, vc, res, fpcr;
__u32 insn;
+ MOD_INC_USE_COUNT;
+
get_user(insn, (__u32*)pc);
fc = (insn >> 0) & 0x1f; /* destination register */
func = (insn >> 5) & 0x7ff;
va = alpha_read_fp_reg(fa);
vb = alpha_read_fp_reg(fb);
-
fpcr = rdfpcr();
+
/*
* Try the operation in software. First, obtain the rounding
* mode...
default:
printk("alpha_fp_emul: unexpected function code %#lx at %#lx\n",
func & 0x3f, pc);
+ MOD_DEC_USE_COUNT;
return 0;
}
+
/*
* Take the appropriate action for each possible
* floating-point result:
wrfpcr(fpcr);
/* Do we generate a signal? */
- if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK)
+ if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) {
+ MOD_DEC_USE_COUNT;
return 0;
+ }
}
/*
* result:
*/
alpha_write_fp_reg(fc, vc);
+
+ MOD_DEC_USE_COUNT;
return 1;
}
* Copyright (C) 1995 Linus Torvalds
*/
-#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/head.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#undef __EXTERN_INLINE
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/head.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
-#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/mmu_context.h>
+
+extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
+
#ifdef __SMP__
unsigned long last_asn[NR_CPUS] = { /* gag */
unsigned long asn_cache = ASN_FIRST_VERSION;
#endif /* __SMP__ */
-#ifndef BROKEN_ASN
/*
- * Select a new ASN and reload the context. This is
- * not inlined as this expands to a pretty large
- * function.
+ * Select a new ASN for a task.
*/
-void get_new_asn_and_reload(struct task_struct *tsk, struct mm_struct *mm)
+
+void
+get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
{
- mm->context = 0;
- get_new_mmu_context(tsk, mm);
- reload_context(tsk);
-}
-#endif
+ unsigned long asn = asn_cache;
-extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
+ if ((asn & HARDWARE_ASN_MASK) < MAX_ASN)
+ ++asn;
+ else {
+ tbiap();
+ imb();
+ asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
+ }
+ asn_cache = asn;
+ mm->context = asn; /* full version + asn */
+ p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */
+}
/*
* This routine handles page faults. It determines the address,
*/
/* Macro for exception fixup code to access integer registers. */
-#define dpf_reg(r) \
- (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
+#define dpf_reg(r) \
+ (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
(r) <= 18 ? (r)+8 : (r)-10])
-asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
- long cause, struct pt_regs *regs)
+asmlinkage void
+do_page_fault(unsigned long address, unsigned long mmcsr,
+ long cause, struct pt_regs *regs)
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
struct pgtable_cache_struct quicklists;
#endif
-void __bad_pmd(pgd_t *pgd)
+void
+__bad_pmd(pgd_t *pgd)
{
printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
pgd_set(pgd, BAD_PAGETABLE);
}
-void __bad_pte(pmd_t *pmd)
+void
+__bad_pte(pmd_t *pmd)
{
printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
}
-pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
+pmd_t *
+get_pmd_slow(pgd_t *pgd, unsigned long offset)
{
pmd_t *pmd;
return (pmd_t *) pgd_page(*pgd) + offset;
}
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+pte_t *
+get_pte_slow(pmd_t *pmd, unsigned long offset)
{
pte_t *pte;
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
-pmd_t * __bad_pagetable(void)
+pmd_t *
+__bad_pagetable(void)
{
memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
return (pmd_t *) EMPTY_PGT;
}
-pte_t __bad_page(void)
+pte_t
+__bad_page(void)
{
memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
}
-void show_mem(void)
+void
+show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
- int shared = 0, cached = 0;
+ long i,free = 0,total = 0,reserved = 0;
+ long shared = 0, cached = 0;
printk("\nMem-info:\n");
show_free_areas();
else
shared += atomic_read(&mem_map[i].count) - 1;
}
- printk("%d pages of RAM\n",total);
- printk("%d free pages\n",free);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
- printk("%d pages in page table cache\n",pgtable_cache_size);
+ printk("%ld pages of RAM\n",total);
+ printk("%ld free pages\n",free);
+ printk("%ld reserved pages\n",reserved);
+ printk("%ld pages shared\n",shared);
+ printk("%ld pages swap cached\n",cached);
+ printk("%ld pages in page table cache\n",pgtable_cache_size);
show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
extern unsigned long free_area_init(unsigned long, unsigned long);
-static struct thread_struct * load_PCB(struct thread_struct * pcb)
+static struct thread_struct *
+load_PCB(struct thread_struct * pcb)
{
- struct thread_struct *old_pcb;
-
- __asm__ __volatile__(
- "stq $30,0(%1)\n\t"
- "bis %1,%1,$16\n\t"
-#ifdef CONFIG_ALPHA_DP264
- "zap $16,0xe0,$16\n\t"
-#endif /* DP264 */
- "call_pal %2\n\t"
- "bis $0,$0,%0"
- : "=r" (old_pcb)
- : "r" (pcb), "i" (PAL_swpctx)
- : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
- return old_pcb;
+ register unsigned long sp __asm__("$30");
+ pcb->ksp = sp;
+ return __reload_tss(pcb);
}
/*
* paging_init() sets up the page tables: in the alpha version this actually
* unmaps the bootup page table (as we're now in KSEG, so we don't need it).
*/
-unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
+unsigned long
+paging_init(unsigned long start_mem, unsigned long end_mem)
{
int i;
unsigned long newptbr;
* note that current should be pointing at the idle thread task struct
* for this CPU.
*/
-void paging_init_secondary(void)
+void
+paging_init_secondary(void)
{
current->tss.ptbr = init_task.tss.ptbr;
current->tss.pal_flags = 1;
}
#endif /* __SMP__ */
-void mem_init(unsigned long start_mem, unsigned long end_mem)
+void
+mem_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long tmp;
return;
}
-void free_initmem (void)
+void
+free_initmem (void)
{
extern char __init_begin, __init_end;
unsigned long addr;
(&__init_end - &__init_begin) >> 10);
}
-void si_meminfo(struct sysinfo *val)
+void
+si_meminfo(struct sysinfo *val)
{
int i;
.long SYMBOL_NAME(sys_lseek)
.long SYMBOL_NAME(sys_getpid) /* 20 */
.long SYMBOL_NAME(sys_mount)
- .long SYMBOL_NAME(sys_umount)
+ .long SYMBOL_NAME(sys_oldumount)
.long SYMBOL_NAME(sys_setuid)
.long SYMBOL_NAME(sys_getuid)
.long SYMBOL_NAME(sys_stime) /* 25 */
.long SYMBOL_NAME(sys_geteuid)
.long SYMBOL_NAME(sys_getegid) /* 50 */
.long SYMBOL_NAME(sys_acct)
- .long SYMBOL_NAME(sys_ni_syscall) /* old phys syscall holder */
+ .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
.long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
.long SYMBOL_NAME(sys_ioctl)
.long SYMBOL_NAME(sys_fcntl) /* 55 */
#endif
xorl %eax,%eax
lldt %ax
- pushl %eax # These are the parameters to main :-)
- pushl %eax
- pushl %eax
cld # gcc2 wants the direction flag cleared at all times
call SYMBOL_NAME(start_kernel)
L6:
#include <linux/console.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/io.h>
#include <asm/smp.h>
/*
extern int root_mountflags;
extern int _etext, _edata, _end;
-extern char empty_zero_page[PAGE_SIZE];
-
/*
* This is set up by the setup-routine at boot-time
*/
-#define PARAM empty_zero_page
+#define PARAM ((unsigned char *)empty_zero_page)
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
#ifdef CONFIG_APM
return 1;
}
+/*
+ * Cyrix CPU configuration register indexes
+ */
+#define CX86_CCR2 0xc2
+#define CX86_CCR3 0xc3
+#define CX86_CCR4 0xe8
+#define CX86_CCR5 0xe9
+#define CX86_DIR0 0xfe
+#define CX86_DIR1 0xff
+
+/*
+ * Cyrix CPU indexed register access macros
+ */
+
+#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
+
+#define setCx86(reg, data) do { \
+ outb((reg), 0x22); \
+ outb((data), 0x23); \
+} while (0)
+
/*
* Use the Cyrix DEVID CPU registers if avail. to get more detailed info.
*/
extern int soc_probe(void);
#endif
struct gendisk *p;
- int nr=0;
#ifdef CONFIG_PARPORT
parport_init();
console_map_init();
#endif
- for (p = gendisk_head ; p ; p=p->next) {
+ for (p = gendisk_head ; p ; p=p->next)
setup_dev(p);
- nr += p->nr_real;
- }
+
#ifdef CONFIG_BLK_DEV_RAM
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && mount_initrd) initrd_load();
md_setup_drive();
#endif
}
+
+#ifdef CONFIG_PROC_FS
+int get_partition_list(char * page)
+{
+ struct gendisk *p;
+ char buf[8];
+ int n, len;
+
+ len = sprintf(page, "major minor #blocks name\n\n");
+ for (p = gendisk_head; p; p = p->next) {
+ for (n=0; n < (p->nr_real << p->minor_shift); n++) {
+ if (p->part[n].nr_sects && len < PAGE_SIZE - 80) {
+ len += sprintf(page+len,
+ "%4d %4d %10d %s\n",
+ p->major, n, p->sizes[n],
+ disk_name(p, n, buf));
+ }
+ }
+ }
+ return len;
+}
+#endif
* Copyright 1993 by Theodore Ts'o. Redistribution of this file is
* permitted under the GNU Public License.
*
- * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
* DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993
+ * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
*
* Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
- *
* Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996
*
- * Fixed do_loop_request() re-entrancy - <Vincent.Renardias@waw.com> Mar 20, 1997
+ * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997
*
* Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998
*/
lo->lo_backing_file->f_op = file->f_op;
lo->lo_backing_file->private_data = file->private_data;
- error = 0;
+ error = get_write_access(inode); /* cannot fail */
+ if (error) {
+ fput(lo->lo_backing_file);
+ lo->lo_backing_file = NULL;
+ }
}
}
if (error)
ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
hwif->dmaproc = &trm290_dmaproc;
hwif->selectproc = &trm290_selectproc;
- hwif->no_autodma = 1; /* play it safe for now */
+ hwif->autodma = 0; /* play it safe for now */
#if 1
{
/*
return APM_SUCCESS;
}
+#if 0
+/* not used anywhere */
static int apm_get_battery_status(u_short which,
u_short *bat, u_short *life, u_short *nbat)
{
return (error >> 8);
return APM_SUCCESS;
}
+#endif
static inline int apm_engage_power_management(u_short device)
{
mem=vmalloc(size);
if (mem)
{
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
adr=(unsigned long) mem;
while (size > 0)
{
BT848_COLOR_FMT_RGB24,
BT848_COLOR_FMT_RGB32,
BT848_COLOR_FMT_RGB15,
+ BT848_COLOR_FMT_YUY2,
+ BT848_COLOR_FMT_BtYUV,
+ -1,
+ -1,
+ -1,
+ BT848_COLOR_FMT_RAW,
+ BT848_COLOR_FMT_YCrCb422,
+ BT848_COLOR_FMT_YCrCb411,
};
+#define PALETTEFMT_MAX 11
static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re, unsigned int *vbuf)
*/
vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame);
- if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
- return -EAGAIN;
+/* if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
+ return -EAGAIN; */
ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
re=ro+2048;
btv->gwidth=mp->width;
btv->gheight=mp->height;
- btv->gfmt=mp->format;
+ if (mp->format > PALETTEFMT_MAX)
+ return -EINVAL;
+ btv->gfmt=palette2fmt[mp->format];
+ if(btv->gfmt==-1)
+ return -EINVAL;
+
make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt);
/* bt848_set_risc_jmps(btv); */
btor(3, BT848_CAP_CTL);
v.rangehigh=0xFFFFFFFF;
v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
v.mode = btv->win.norm;
+ v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
if(copy_to_user(arg,&v,sizeof(v)))
return -EFAULT;
return 0;
bttv_close,
bttv_read,
bttv_write,
+ NULL, /* poll */
bttv_ioctl,
bttv_mmap,
bttv_init_done,
return count;
}
+static unsigned int vbi_poll(struct video_device *dev, struct file *file,
+ poll_table *wait)
+{
+ struct bttv *btv=(struct bttv *)(dev-2);
+ unsigned int mask = 0;
+
+ poll_wait(file, &btv->vbiq, wait);
+
+ if (btv->vbip < VBIBUF_SIZE)
+ mask |= (POLLIN | POLLRDNORM);
+
+ return mask;
+}
+
static int vbi_open(struct video_device *dev, int flags)
{
struct bttv *btv=(struct bttv *)(dev-2);
vbi_close,
vbi_read,
bttv_write,
+ vbi_poll,
vbi_ioctl,
NULL, /* no mmap yet */
bttv_init_done,
radio_close,
radio_read, /* just returns -EINVAL */
bttv_write, /* just returns -EINVAL */
+ NULL, /* no poll */
radio_ioctl,
NULL, /* no mmap */
bttv_init_done, /* just returns 0 */
for (dev = pci_devices; dev != NULL; dev = dev->next)
{
if (dev->class != PCI_CLASS_NOT_DEFINED_VGA &&
- (dev->class) >> 8 != PCI_BASE_CLASS_DISPLAY)
+ ((dev->class) >> 16 != PCI_BASE_CLASS_DISPLAY))
{
continue;
}
badr=vbs[i].badr;
break;
}
- if (!badr)
- {
- printk(KERN_ERR "bttv: Unknown video memory base address.\n");
- continue;
- }
- pci_read_config_dword(dev, badr, &vidadr);
- if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
- {
- printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
- printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
- continue;
- }
- vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
- if (!vidadr)
- {
- printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!");
- continue;
- }
-
- if (dev->vendor == PCI_VENDOR_ID_DEC &&
- dev->device == PCI_DEVICE_ID_DEC_TGA)
+ }
+ if (!badr)
+ {
+ printk(KERN_ERR "bttv: Unknown video memory base address.\n");
+ continue;
+ }
+ pci_read_config_dword(dev, badr, &vidadr);
+ if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
+ printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
+ continue;
+ }
+ vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
+ if (!vidadr)
+ {
+ printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!");
+ continue;
+ }
+
+ if (dev->vendor == PCI_VENDOR_ID_DEC &&
+ dev->device == PCI_DEVICE_ID_DEC_TGA)
+ {
+ tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
+ if (tga_type != 0 && tga_type != 1 && tga_type != 3)
{
- tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
- if (tga_type != 0 && tga_type != 1 && tga_type != 3)
- {
- printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
- found--;
- }
- vidadr+=dec_offsets[tga_type];
+ printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
+ found--;
}
- DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
- DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn));
- found++;
+ vidadr+=dec_offsets[tga_type];
}
+ DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
+ DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn));
+ found++;
}
if (vidmem)
if (!(btv->grisc=(unsigned int *) kmalloc(32768, GFP_KERNEL)))
return -1;
+ memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random
+ memory to the user */
btv->fbuffer=NULL;
bt848_muxsel(btv, 1);
qcam_close,
qcam_read,
qcam_write,
+ NULL,
qcam_ioctl,
NULL,
qcam_init_done,
qcam_close,
qcam_read,
qcam_write,
+ NULL,
qcam_ioctl,
NULL,
qcam_init_done,
info->idle_stats.recv_bytes,
JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ,
info->idle_stats.overruns,
- info->tty->ldisc.num);
+ (long) info->tty->ldisc.num);
else
size = sprintf(buf+len,
"%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n",
* Diacriticals redone & other small changes, aeb@cwi.nl, June 1993
* Added decr/incr_console, dynamic keymaps, Unicode support,
* dynamic function/string keys, led setting, Sept 1994
- *
* `Sticky' modifier keys, 951006.
+ *
* 11-11-96: SAK should now work in the raw mode (Martin Mares)
*
* Modified to provide 'generic' keyboard support by Hamish Macdonald
if (ch == ' ' || ch == d)
return d;
+ put_queue(d);
return ch;
}
return -ENXIO;
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENXIO;
- if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)) & LP_BUSY)
+ if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)))
return -EBUSY;
MOD_INC_USE_COUNT;
#endif
-int debug = 0; /* insmod parameter */
+static int debug = 0; /* insmod parameter */
struct msp3400c {
struct i2c_bus *bus;
LOCK_I2C_BUS(msp->bus);
msp3400c_setvolume(msp->bus, 0, 0);
msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
- val1 = val2 = max1 = max2 = 0;
+ val1 = val2 = 0;
+ max1 = max2 = -1;
del_timer(&msp->wake_stereo);
msp->watch_stereo = 0;
*/
/*
- * Some x86 BIOSes do not correctly initializes the keyboard, so the
+ * Some x86 BIOSes do not correctly initialize the keyboard, so the
* "kbd-reset" command line options can be given to force a reset.
* [Ranger]
*/
pms_close,
pms_read,
pms_write,
+ NULL, /* FIXME - we can use POLL on this board with the irq */
pms_ioctl,
NULL,
pms_init_done,
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
*/
+#include <linux/config.h>
#include <linux/module.h> /* For EXPORT_SYMBOL */
#include <linux/errno.h>
/* adapted from radio-aztech.c */
- freq = (freq * 100) / 16; /* massage the data a little */
+ /* We want to compute x * 100 / 16 without overflow
+ * So we compute x*6 + (x/100)*25 to give x*6.25
+ */
+
+ freq = freq * 6 + freq/4; /* massage the data a little */
freq += 1070; /* IF = 10.7 MHz */
freq /= 5; /* ref = 25 kHz */
rt_close,
NULL, /* Can't read (no capture ability) */
NULL, /* Can't write */
+ NULL, /* No poll */
rt_ioctl,
NULL,
NULL
{
int i;
- frequency = (frequency * 100) / 16; /* massage data a bit */
+ /* 6.25 * */
+ frequency = frequency*6 + frequency/4; /* massage data a bit */
frequency += 1070; /* tuning needs 24 data bits */
frequency /= 5;
az_close,
NULL, /* Can't read (no capture ability) */
NULL, /* Can't write */
+ NULL, /* No poll */
az_ioctl,
NULL,
NULL
--- /dev/null
+/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
+ *
+ * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
+ * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
+ *
+ * TODO: Allow for more than one of these foolish entities :-)
+ *
+ */
+
+#include <linux/module.h> /* Modules */
+#include <linux/init.h> /* Initdata */
+#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/delay.h> /* udelay */
+#include <asm/io.h> /* outb, outb_p */
+#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/videodev.h> /* kernel radio structs */
+#include <linux/config.h> /* CONFIG_RADIO_RTRACK2_PORT */
+
+#ifndef CONFIG_RADIO_RTRACK2_PORT
+#define CONFIG_RADIO_RTRACK2_PORT -1
+#endif
+
+static int io = CONFIG_RADIO_RTRACK2_PORT;
+static int users = 0;
+
+struct rt_device
+{
+ int port;
+ unsigned long curfreq;
+ int muted;
+};
+
+
+/* local things */
+
+static void rt_mute(struct rt_device *dev)
+{
+ if(dev->muted)
+ return;
+ outb(1, io);
+ dev->muted = 1;
+}
+
+static void rt_unmute(struct rt_device *dev)
+{
+ if(dev->muted == 0)
+ return;
+ outb(0, io);
+ dev->muted = 0;
+}
+
+static void zero(void)
+{
+ outb_p(1, io);
+ outb_p(3, io);
+ outb_p(1, io);
+}
+
+static void one(void)
+{
+ outb_p(5, io);
+ outb_p(7, io);
+ outb_p(5, io);
+}
+
+static int rt_setfreq(struct rt_device *dev, unsigned long freq)
+{
+ int i;
+
+ freq = freq / 200 + 856;
+
+ outb_p(0xc8, io);
+ outb_p(0xc9, io);
+ outb_p(0xc9, io);
+
+ for (i = 0; i < 10; i++)
+ zero ();
+
+ for (i = 14; i >= 0; i--)
+ if (freq & (1 << i))
+ one ();
+ else
+ zero ();
+
+ outb_p(0xc8, io);
+ if (!dev->muted)
+ outb_p(0, io);
+ return 0;
+}
+
+int rt_getsigstr(struct rt_device *dev)
+{
+ if (inb(io) & 2) /* bit set = no signal present */
+ return 0;
+ return 1; /* signal present */
+}
+
+static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ struct rt_device *rt=dev->priv;
+
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type=VID_TYPE_TUNER;
+ v.channels=1;
+ v.audios=1;
+ /* No we don't do pictures */
+ v.maxwidth=0;
+ v.maxheight=0;
+ v.minwidth=0;
+ v.minheight=0;
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg,sizeof(v))!=0)
+ return -EFAULT;
+ if(v.tuner) /* Only 1 tuner */
+ return -EINVAL;
+ v.rangelow=88*16000;
+ v.rangehigh=108*16000;
+ v.flags=VIDEO_TUNER_LOW;
+ v.mode=VIDEO_MODE_AUTO;
+ v.signal=0xFFFF*rt_getsigstr(rt);
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.tuner!=0)
+ return -EINVAL;
+ /* Only 1 tuner so no setting needed ! */
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq)))
+ return -EFAULT;
+ rt_setfreq(rt, rt->curfreq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v,0, sizeof(v));
+ v.flags|=VIDEO_AUDIO_MUTABLE;
+ v.volume=1;
+ strcpy(v.name, "Radio");
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.audio)
+ return -EINVAL;
+
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ rt_mute(rt);
+ else
+ rt_unmute(rt);
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int rt_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void rt_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+static struct rt_device rtrack2_unit;
+
+static struct video_device rtrack2_radio=
+{
+ "RadioTrack II radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_RTRACK2,
+ rt_open,
+ rt_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* Can't poll */
+ rt_ioctl,
+ NULL,
+ NULL
+};
+
+__initfunc(int rtrack2_init(struct video_init *v))
+{
+ if (check_region(io, 4))
+ {
+ printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
+
+ rtrack2_radio.priv=&rtrack2_unit;
+
+ if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io, 4, "rtrack2");
+ printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
+
+ /* mute card - prevents noisy bootups */
+ outb(1, io);
+ rtrack2_unit.muted = 1;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Ben Pfaff");
+MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
+ return -EINVAL;
+ }
+ return rtrack2_init(NULL);
+}
+
+void cleanup_module(void)
+{
+ video_unregister_device(&rtrack2_radio);
+ release_region(io,4);
+}
+
+#endif
+
+/*
+ Local variables:
+ compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c"
+ End:
+*/
int port;
int curvol;
unsigned long curfreq;
+ int flags;
};
#ifndef CONFIG_RADIO_SF16FMI_PORT
static int users = 0;
/* local things */
-#define RSF16_ENCODE(x) ((x*(1000/4)+10700)/50)
+/* freq in 1/16kHz to internal number */
+#define RSF16_ENCODE(x) ((x/16+10700)/50)
static void outbits(int bits, int data, int port)
{
outb(0x08, port);
}
-/* FREQ is in 1/16ths of a MHz so this is probably wrong atm */
-
static int fmi_setfreq(struct fmi_device *dev, unsigned long freq)
{
int myport = dev->port;
return -EFAULT;
if(v.tuner) /* Only 1 tuner */
return -EINVAL;
- v.rangelow=(int)(87.5*16);
- v.rangehigh=(int)(108.0*16);
- v.flags=0;
+ if (fmi->flags & VIDEO_TUNER_LOW) {
+ v.rangelow = 87500 * 16;
+ v.rangehigh = 108000 * 16;
+ } else {
+ v.rangelow=(int)(175*8 /* 87.5 *16 */);
+ v.rangehigh=(int)(108*16);
+ }
+ v.flags=fmi->flags;
v.mode=VIDEO_MODE_AUTO;
v.signal=0xFFFF*fmi_getsigstr(fmi);
if(copy_to_user(arg,&v, sizeof(v)))
return -EFAULT;
if(v.tuner!=0)
return -EINVAL;
+ fmi->flags = v.flags & VIDEO_TUNER_LOW;
/* Only 1 tuner so no setting needed ! */
return 0;
}
case VIDIOCGFREQ:
- if(copy_to_user(arg, &fmi->curfreq, sizeof(fmi->curfreq)))
+ {
+ unsigned long tmp = fmi->curfreq;
+ if (!(fmi->flags & VIDEO_TUNER_LOW))
+ tmp /= 1000;
+ if(copy_to_user(arg, &tmp, sizeof(tmp)))
return -EFAULT;
return 0;
+ }
case VIDIOCSFREQ:
- if(copy_from_user(&fmi->curfreq, arg,sizeof(fmi->curfreq)))
+ {
+ unsigned long tmp;
+ if(copy_from_user(&tmp, arg, sizeof(tmp)))
return -EFAULT;
+ if (!(fmi->flags & VIDEO_TUNER_LOW))
+ tmp *= 1000;
+ fmi->curfreq = tmp;
fmi_setfreq(fmi, fmi->curfreq);
return 0;
+ }
case VIDIOCGAUDIO:
{
struct video_audio v;
fmi_close,
NULL, /* Can't read (no capture ability) */
NULL, /* Can't write */
+ NULL, /* Can't poll */
fmi_ioctl,
NULL,
NULL
}
fmi_unit.port=io;
+ fmi_unit.flags = VIDEO_TUNER_LOW;
fmi_radio.priv=&fmi_unit;
if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1)
* (c) 1998 C. van Schaik <carl@leg.uct.ac.za>
*
* BUGS
- * The signal strength query is unsurprisingly inaccurate. And it seems
- * to indicate that (on my card, at least) the frequency setting isn't
- * too great. It seems to work in a similar way to a car stereo which
- * flickers when it is near or on a station...
+ * Due to the inconsistancy in reading from the signal flags
+ * it is difficult to get an accurate tuned signal.
*
* There seems to be a problem with the volume setting that I must still
- * figure out. This is a minor problem... It still works but you may
- * have to set the card lounder to get the same volume.
+ * figure out.
+ * It seems that the card has is not linear to 0 volume. It cuts off
+ * at a low frequency, and it is not possible (at least I have not found)
+ * to get fine volume control over the low volume range.
*
* Some code derived from code by Frans Brinkman
*/
inb(io + 3); /* Zoltrix needs to be read to confirm */
}
-static int zol_setvol(struct zol_device *dev, int vol)
+static void zol_on(int vol)
{
- int l;
+ int l;
+ outb(vol, io);
+ sleep_delay(10000);
+ l = inb(io + 2);
+}
+static int zol_setvol(struct zol_device *dev, int vol)
+{
if (vol == dev->curvol) { /* requested volume = current */
if (dev->muted) { /* user is unmuting the card */
dev->muted = 0;
- outb(vol, io);
- sleep_delay(20000);
- l = inb(io + 2);
+ zol_on(vol);
}
return 0;
}
if (vol == 0) { /* volume = 0 means mute the card */
- outb(0, io);
- outb(0, io);
- l = inb(io + 3);
+ zol_mute(dev);
return 0;
}
dev->muted = 0;
dev->curvol = vol;
- outb(vol, io);
- sleep_delay(20000);
- l = inb(io + 2);
+ zol_on(vol);
return 0;
}
{
/* tunes the radio to the desired frequency */
unsigned long long bitmask, f, m;
- int i, l;
+ int i;
m = (freq * 25 / 4 - 8800) * 2;
f = (unsigned long long) m + 0x4d1c;
bitmask = 0xc480402c10080000ull;
i = 45;
- outb(0x00, io);
- outb(0x00, io);
- sleep_delay(10000);
- inb(io + 3);
+ zol_mute(dev);
+
outb(0x40, io);
outb(0xc0, io);
outb(0x80, io);
outb(0xc0, io);
outb(0x40, io);
- outb(0x00, io);
- sleep_delay(10000);
- l = inb(io + 2);
- sleep_delay(10000);
- l = inb(io + 1);
- outb(dev->curvol, io);
- sleep_delay(10000);
- l = inb(io + 2);
+ zol_on(dev->curvol);
return 0;
}
-/* Get signal strenght */
+/* Get signal strength */
+
int zol_getsigstr(struct zol_device *dev)
{
int a, b;
- outb(0x00, io);
- sleep_delay(10000);
- a = inb(io + 2);
+
+ outb(0x00, io); /* This stuff I found to do nothing */
+ outb(dev->curvol, io);
sleep_delay(20000);
- b = inb(io + 1);
- outb(0x00, io);
- if (((a | b) & 255) != 0x0ff)
+ a = inb(io);
+ sleep_delay(1000);
+ b = inb(io);
+
+ if ((a == b) && (a == 0xdf)) /* I found this out by playing */
+ /* with a binary scanner on the card io */
return (1);
else
return (0);
struct video_audio v;
memset(&v, 0, sizeof(v));
v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
- v.volume = rt->curvol * 6554;
+ v.volume = rt->curvol * 4095;
strcpy(v.name, "Radio");
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
if (v.flags & VIDEO_AUDIO_MUTE)
zol_mute(rt);
else
- zol_setvol(rt, v.volume / 6554);
+ zol_setvol(rt, v.volume / 4096);
return 0;
}
zol_close,
NULL, /* Can't read (no capture ability) */
NULL, /* Can't write */
+ NULL,
zol_ioctl,
NULL,
NULL
}
-
/*
* Write for now does nothing. No reason it shouldnt do overlay setting
* for some boards I guess..
return 0;
}
+
+/*
+ * Poll to see if we're readable, can probably be used for timing on incoming
+ * frames, etc..
+ */
+
+static unsigned int video_poll(struct file *file, poll_table * wait)
+{
+ struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+ if(vfl->poll)
+ return vfl->poll(vfl, file, wait);
+ else
+ return 0;
+}
+
/*
* Open a video device.
*/
video_read,
video_write,
NULL, /* readdir */
- NULL, /* poll */
+ video_poll, /* poll */
video_ioctl,
video_mmap,
video_open,
}
#ifdef CONFIG_MCA
+#warning "The MCA code in drivers/net/3c509.c does not compile"
+#warning "See http://glycerine.itsmm.uni.edu/mca/ for patches."
+#if 0
if (MCA_bus) {
mca_adaptor_select_mode(1);
for (i = 0; i < 8; i++)
mca_adaptor_select_mode(0);
}
+#endif
#endif
/* Reset the ISA PnP mechanism on 3c509b. */
if (inb(id_port) & 0x01)
break;
}
- if (id_port >= 0x200) { /* GCC optimizes this test out. */
+ if (id_port >= 0x200) {
/* Rare -- do we really need a warning? */
printk(" WARNING: No I/O port available for 3c509 activation.\n");
return -ENODEV;
return TIMEOUT;
}
c0 = inb(PAR_STATUS(dev));
- printk("%s: transmit timeout(%d,%02x)\n",
+ printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n",
dev->name, snd->state, c0);
}
nl->enet_stats.tx_errors++;
return TIMEOUT;
}
c0 = inb(PAR_STATUS(dev));
- printk("%s: receive timeout(%d,%02x)\n",
+ printk(KERN_WARNING "%s: receive timeout(%d,%02x)\n",
dev->name, rcv->state, c0);
}
nl->enet_stats.rx_dropped++;
dev->interrupt = 0;
outb(0x01, PAR_DATA(dev)); /* send ACK */
if (net_debug > 2)
- printk("%s: receive start\n", dev->name);
+ printk(KERN_DEBUG "%s: receive start\n", dev->name);
rcv->state = PLIP_PK_LENGTH_LSB;
rcv->nibble = PLIP_NB_BEGIN;
return TIMEOUT;
if (rcv->length.h > dev->mtu + dev->hard_header_len
|| rcv->length.h < 8) {
- printk("%s: bogus packet size %d.\n", dev->name, rcv->length.h);
+ printk(KERN_WARNING "%s: bogus packet size %d.\n", dev->name, rcv->length.h);
return ERROR;
}
/* Malloc up new buffer. */
rcv->skb = dev_alloc_skb(rcv->length.h);
if (rcv->skb == NULL) {
- printk("%s: Memory squeeze.\n", dev->name);
+ printk(KERN_WARNING "%s: Memory squeeze.\n", dev->name);
return ERROR;
}
skb_put(rcv->skb,rcv->length.h);
if (rcv->data != rcv->checksum) {
nl->enet_stats.rx_crc_errors++;
if (net_debug)
- printk("%s: checksum error\n", dev->name);
+ printk(KERN_DEBUG "%s: checksum error\n", dev->name);
return ERROR;
}
rcv->state = PLIP_PK_DONE;
nl->enet_stats.rx_packets++;
rcv->skb = NULL;
if (net_debug > 2)
- printk("%s: receive end\n", dev->name);
+ printk(KERN_DEBUG "%s: receive end\n", dev->name);
/* Close the connection. */
outb (0x00, PAR_DATA(dev));
unsigned int cx;
if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) {
- printk("%s: send skb lost\n", dev->name);
+ printk(KERN_ERR "%s: send skb lost\n", dev->name);
snd->state = PLIP_PK_DONE;
snd->skb = NULL;
return ERROR;
}
outb(PAR_INTR_OFF, PAR_CONTROL(dev));
if (net_debug > 2)
- printk("%s: send start\n", dev->name);
+ printk(KERN_DEBUG "%s: send start\n", dev->name);
snd->state = PLIP_PK_LENGTH_LSB;
snd->nibble = PLIP_NB_BEGIN;
nl->timeout_count = 0;
outb (0x00, data_addr);
snd->skb = NULL;
if (net_debug > 2)
- printk("%s: send end\n", dev->name);
+ printk(KERN_DEBUG "%s: send end\n", dev->name);
nl->connection = PLIP_CN_CLOSING;
nl->is_deferred = 1;
queue_task(&nl->deferred, &tq_timer);
status = inb(PAR_STATUS(dev));
if ((status & 0xf8) == 0x80) {
if (net_debug > 2)
- printk("%s: reset interface.\n", dev->name);
+ printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
nl->connection = PLIP_CN_NONE;
nl->should_relinquish = 0;
dev->tbusy = 0;
unsigned char c0;
if (dev == NULL) {
- printk("plip_interrupt: irq %d for unknown device.\n", irq);
+ printk(KERN_ERR "plip_interrupt: irq %d for unknown device.\n", irq);
return;
}
c0 = inb(PAR_STATUS(dev));
if ((c0 & 0xf8) != 0xc0) {
if (net_debug > 1)
- printk("%s: spurious interrupt\n", dev->name);
+ printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name);
return;
}
dev->interrupt = 1;
if (net_debug > 3)
- printk("%s: interrupt.\n", dev->name);
+ printk(KERN_DEBUG "%s: interrupt.\n", dev->name);
spin_lock_irq(&nl->lock);
switch (nl->connection) {
case PLIP_CN_ERROR:
spin_unlock_irq(&nl->lock);
- printk("%s: receive interrupt in error state\n", dev->name);
+ printk(KERN_WARNING "%s: receive interrupt in error state\n", dev->name);
break;
}
}
}
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
return 1;
}
if (skb->len > dev->mtu + dev->hard_header_len) {
- printk("%s: packet too big, %d.\n", dev->name, (int)skb->len);
+ printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);
dev->tbusy = 0;
return 0;
}
if (net_debug > 2)
- printk("%s: send request\n", dev->name);
+ printk(KERN_DEBUG "%s: send request\n", dev->name);
spin_lock_irq(&nl->lock);
dev->trans_start = jiffies;
return r;
}
-static int
-plip_config(struct device *dev, struct ifmap *map)
+static int plip_config(struct device *dev, struct ifmap *map)
{
struct net_local *nl = (struct net_local *) dev->priv;
struct pardevice *pardev = nl->pardev;
if (dev->flags & IFF_UP)
return -EBUSY;
- printk(KERN_WARNING "plip: Warning, changing irq with ifconfig will be obsoleted.\n");
- printk("plip: Next time, please set with /proc/parport/*/irq instead.\n");
+ printk(KERN_INFO "plip: Warning, changing irq with ifconfig will be obsoleted.\n");
+ printk(KERN_INFO "plip: Next time, please set with /proc/parport/*/irq instead.\n");
if (map->irq != (unsigned char)-1) {
pardev->port->irq = dev->irq = map->irq;
static void shaper_setspeed(struct shaper *shaper, int bitspersec)
{
+ shaper->bitspersec=bitspersec;
shaper->bytespertick=(bitspersec/HZ)/8;
if(!shaper->bytespertick)
shaper->bytespertick++;
{
struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data;
struct shaper *sh=dev->priv;
- struct device *them=dev_get(ss->ss_name);
switch(ss->ss_cmd)
{
case SHAPER_SET_DEV:
+ {
+ struct device *them=dev_get(ss->ss_name);
if(them==NULL)
return -ENODEV;
if(sh->dev)
return -EBUSY;
return shaper_attach(dev,dev->priv, them);
+ }
+ case SHAPER_GET_DEV:
+ if(sh->dev==NULL)
+ return -ENODEV;
+ memcpy(ss->ss_name, sh->dev->name, sizeof(ss->ss_name));
+ return 0;
case SHAPER_SET_SPEED:
shaper_setspeed(sh,ss->ss_speed);
return 0;
+ case SHAPER_GET_SPEED:
+ ss->ss_speed=sh->bitspersec;
+ return 0;
default:
return -EINVAL;
}
static struct device *TLanDevices = NULL;
static int TLanDevicesInstalled = 0;
+static int aui = 0;
+static int sa_int = 0;
+static int duplex = 0;
+static int speed = 0;
+
#endif
static int debug = 0;
-static int aui = 0;
-static int sa_int = 0;
static int bbuf = 0;
-static int duplex = 0;
-static int speed = 0;
static u8 *TLanPadBuffer;
static char TLanSignature[] = "TLAN";
static int TLanVersionMajor = 1;
#define TLan_GetBit( bit, port ) ((int) (inb_p(port) & bit))
#define TLan_SetBit( bit, port ) outb_p(inb_p(port) | bit, port)
+#ifdef I_LIKE_A_FAST_HASH_FUNCTION
+/* given 6 bytes, view them as 8 6-bit numbers and return the XOR of those */
+/* the code below is about seven times as fast as the original code */
+inline u32 TLan_HashFunc( u8 *a )
+{
+ u8 hash;
+
+ hash = (a[0]^a[3]); /* & 077 */
+ hash ^= ((a[0]^a[3])>>6); /* & 003 */
+ hash ^= ((a[1]^a[4])<<2); /* & 074 */
+ hash ^= ((a[1]^a[4])>>4); /* & 017 */
+ hash ^= ((a[2]^a[5])<<4); /* & 060 */
+ hash ^= ((a[2]^a[5])>>2); /* & 077 */
+
+ return (hash & 077);
+}
+
+#else /* original code */
inline u32 xor( u32 a, u32 b )
{
}
-
-
-
+#endif /* I_LIKE_A_FAST_HASH_FUNCTION */
#endif
fb_var.xres = fb_var.xres_virtual = 640;
fb_var.yres = fb_var.yres_virtual = 480;
fb_fix.line_length = 80*fb_var.bits_per_pixel;
- fb_fix.smem_start = (char *)__pa(tga_fb_base + DENSE_MEM(tga_fb_base));
+ fb_fix.smem_start = (char *)__pa(tga_fb_base + dense_mem(tga_fb_base));
fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
fb_fix.type = FB_TYPE_PACKED_PIXELS;
fb_fix.type_aux = 0;
disp.cmap.start = 0;
disp.cmap.len = 0;
disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
- disp.screen_base = (char *)tga_fb_base + DENSE_MEM(tga_fb_base);
+ disp.screen_base = (char *)tga_fb_base + dense_mem(tga_fb_base);
disp.visual = fb_fix.visual;
disp.type = fb_fix.type;
disp.type_aux = fb_fix.type_aux;
*/
vga_video_num_columns = c->vc_cols;
vga_video_num_lines = c->vc_rows;
+ if (vga_is_gfx)
+ return 1;
scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size);
return 0; /* Redrawing not needed */
}
c->vc_x = ORIG_X;
c->vc_y = ORIG_Y;
}
+ if (vga_is_gfx)
+ return;
scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size);
}
static int exec_mmap(void)
{
struct mm_struct * mm, * old_mm;
- int retval;
+ int retval, nr;
if (current->mm->count == 1) {
flush_cache_mm(current->mm);
mm = mm_alloc();
if (!mm)
goto fail_nomem;
+
mm->cpu_vm_mask = (1UL << smp_processor_id());
mm->total_vm = 0;
mm->rss = 0;
+ /*
+ * Make sure we have a private ldt if needed ...
+ */
+ nr = current->tarray_ptr - &task[0];
+ copy_segments(nr, current, mm);
+
old_mm = current->mm;
current->mm = mm;
retval = new_page_tables(current);
/* The pgd belongs to the parent ... don't free it! */
mm->pgd = NULL;
current->mm = old_mm;
+ /* restore the ldt for this task */
+ copy_segments(nr, current, NULL);
mmput(mm);
fail_nomem:
/* If we didn't fill the buffer completely, we're at EOF */
eof = !cd.eob;
- /* Hewlett Packard ignores the eof flag on READDIR. Some
- * fs-specific readdir implementations seem to reset f_pos to 0
- * at EOF however, causing an endless loop. */
- if (cd.offset && !eof)
+ if (cd.offset)
*cd.offset = htonl(file.f_pos);
p = cd.buffer;
* - Incorporation and non-SMP safe operation
* of forissier patch in 2.1.78 by
* Hans Marcus <crowbar@concepts.nl>
+ *
+ * aeb@cwi.nl : /proc/partitions
*/
#include <linux/types.h>
extern int get_ksyms_list(char *, char **, off_t, int);
#endif
extern int get_device_list(char *);
+extern int get_partition_list(char *);
extern int get_filesystem_list(char *);
extern int get_filesystem_info( char * );
extern int get_irq_list(char *);
case PROC_DEVICES:
return get_device_list(page);
+ case PROC_PARTITIONS:
+ return get_partition_list(page);
+
case PROC_INTERRUPTS:
return get_irq_list(page);
extern void free_proc_entry(struct proc_dir_entry *);
void free_proc_entry(struct proc_dir_entry *de)
{
- kfree(de);
+ int ino = de->low_ino;
+
+ if (ino >= PROC_DYNAMIC_FIRST &&
+ ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+ kfree(de);
}
/*
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
+static struct proc_dir_entry proc_root_partitions = {
+ PROC_PARTITIONS, 10, "partitions",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations
+};
static struct proc_dir_entry proc_root_interrupts = {
PROC_INTERRUPTS, 10,"interrupts",
S_IFREG | S_IRUGO, 1, 0, 0,
#endif
proc_register(&proc_root, &proc_root_stat);
proc_register(&proc_root, &proc_root_devices);
+ proc_register(&proc_root, &proc_root_partitions);
proc_register(&proc_root, &proc_root_interrupts);
proc_register(&proc_root, &proc_root_filesystems);
proc_register(&proc_root, &proc_root_fs);
dentry->d_covers = covered;
}
-static int do_umount(kdev_t dev, int unmount_root)
+static int do_umount(kdev_t dev, int unmount_root, int flags)
{
struct super_block * sb;
int retval;
* about for the moment.
*/
- if(sb->s_op->umount_begin)
+ if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
sb->s_op->umount_begin(sb);
/*
return retval;
}
-static int umount_dev(kdev_t dev)
+static int umount_dev(kdev_t dev, int flags)
{
int retval;
struct inode * inode = get_empty_inode();
down(&mount_sem);
- retval = do_umount(dev,0);
+ retval = do_umount(dev, 0, flags);
if (!retval) {
fsync_dev(dev);
if (dev != ROOT_DEV) {
* If any other fields are ever needed by any block device release
* functions, they should be faked here. -- jrs
*
- * For 2.3.x we want a new sys_umount syscall with flags (ie 'force')
+ * We now support a flag for forced unmount like the other 'big iron'
+ * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
*/
-asmlinkage int sys_umount(char * name)
+asmlinkage int sys_umount(char * name, int flags)
{
struct dentry * dentry;
int retval;
dput(dentry);
if (!retval)
- retval = umount_dev(dev);
+ retval = umount_dev(dev, flags);
}
unlock_kernel();
return retval;
}
+/*
+ * The 2.0 compatible umount. No flags.
+ */
+
+asmlinkage int sys_oldumount(char * name)
+{
+ return sys_umount(name,0);
+}
+
/*
* Check whether we can mount the specified device.
*/
int umount_error;
printk(KERN_NOTICE "Trying to unmount old root ... ");
- umount_error = do_umount(old_root_dev,1);
+ umount_error = do_umount(old_root_dev,1, 0);
if (!umount_error) {
printk("okay\n");
invalidate_buffers(old_root_dev);
put_new_inode = 0;
}
+ clear_inode(old_inode);
+
rename_done:
if (locked)
fat_unlock_creation();
+++ /dev/null
-#ifndef __ALPHA_APECS__H__
-#define __ALPHA_APECS__H__
-
-#include <linux/types.h>
-
-/*
- * APECS is the internal name for the 2107x chipset which provides
- * memory controller and PCI access for the 21064 chip based systems.
- *
- * This file is based on:
- *
- * DECchip 21071-AA and DECchip 21072-AA Core Logic Chipsets
- * Data Sheet
- *
- * EC-N0648-72
- *
- *
- * david.rusling@reo.mts.dec.com Initial Version.
- *
- */
-#include <linux/config.h>
-
-#ifdef CONFIG_ALPHA_XL
-/*
- An AVANTI *might* be an XL, and an XL has only 27 bits of ISA address
- that get passed through the PCI<->ISA bridge chip. So we've gotta use
- both windows to max out the physical memory we can DMA to. Sigh...
-
- If we try a window at 0 for 1GB as a work-around, we run into conflicts
- with ISA/PCI bus memory which can't be relocated, like VGA aperture and
- BIOS ROMs. So we must put the windows high enough to avoid these areas.
-
- We put window 1 at BUS 64Mb for 64Mb, mapping physical 0 to 64Mb-1,
- and window 2 at BUS 1Gb for 1Gb, mapping physical 0 to 1Gb-1.
- Yes, this does map 0 to 64Mb-1 twice, but only window 1 will actually
- be used for that range (via virt_to_bus()).
-
- Note that we actually fudge the window 1 maximum as 48Mb instead of 64Mb,
- to keep virt_to_bus() from returning an address in the first window, for
- a data area that goes beyond the 64Mb first DMA window. Sigh...
- The fudge factor MUST match with <asm/dma.h> MAX_DMA_ADDRESS, but
- we can't just use that here, because of header file looping... :-(
-
- Window 1 will be used for all DMA from the ISA bus; yes, that does
- limit what memory an ISA floppy or sound card or Ethernet can touch, but
- it's also a known limitation on other platforms as well. We use the
- same technique that is used on INTEL platforms with similar limitation:
- set MAX_DMA_ADDRESS and clear some pages' DMAable flags during mem_init().
- We trust that any ISA bus device drivers will *always* ask for DMAable
- memory explicitly via kmalloc()/get_free_pages() flags arguments.
-
- Note that most PCI bus devices' drivers do *not* explicitly ask for
- DMAable memory; they count on being able to DMA to any memory they
- get from kmalloc()/get_free_pages(). They will also use window 1 for
- any physical memory accesses below 64Mb; the rest will be handled by
- window 2, maxing out at 1Gb of memory. I trust this is enough... :-)
-
- We hope that the area before the first window is large enough so that
- there will be no overlap at the top end (64Mb). We *must* locate the
- PCI cards' memory just below window 1, so that there's still the
- possibility of being able to access it via SPARSE space. This is
- important for cards such as the Matrox Millennium, whose Xserver
- wants to access memory-mapped registers in byte and short lengths.
-
- Note that the XL is treated differently from the AVANTI, even though
- for most other things they are identical. It didn't seem reasonable to
- make the AVANTI support pay for the limitations of the XL. It is true,
- however, that an XL kernel will run on an AVANTI without problems.
-
-*/
-#define APECS_XL_DMA_WIN1_BASE (64*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE (64*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE_PARANOID (48*1024*1024)
-#define APECS_XL_DMA_WIN2_BASE (1024*1024*1024)
-#define APECS_XL_DMA_WIN2_SIZE (1024*1024*1024)
-
-#else /* CONFIG_ALPHA_XL */
-
-/* these are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64 */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define APECS_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define APECS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int APECS_DMA_WIN_BASE;
-extern unsigned int APECS_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define APECS_DMA_WIN_BASE (1024*1024*1024)
-#define APECS_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-#endif /* CONFIG_ALPHA_XL */
-
-/*
- * 21071-DA Control and Status registers.
- * These are used for PCI memory access.
- */
-#define APECS_IOC_DCSR (IDENT_ADDR + 0x1A0000000UL)
-#define APECS_IOC_PEAR (IDENT_ADDR + 0x1A0000020UL)
-#define APECS_IOC_SEAR (IDENT_ADDR + 0x1A0000040UL)
-#define APECS_IOC_DR1 (IDENT_ADDR + 0x1A0000060UL)
-#define APECS_IOC_DR2 (IDENT_ADDR + 0x1A0000080UL)
-#define APECS_IOC_DR3 (IDENT_ADDR + 0x1A00000A0UL)
-
-#define APECS_IOC_TB1R (IDENT_ADDR + 0x1A00000C0UL)
-#define APECS_IOC_TB2R (IDENT_ADDR + 0x1A00000E0UL)
-
-#define APECS_IOC_PB1R (IDENT_ADDR + 0x1A0000100UL)
-#define APECS_IOC_PB2R (IDENT_ADDR + 0x1A0000120UL)
-
-#define APECS_IOC_PM1R (IDENT_ADDR + 0x1A0000140UL)
-#define APECS_IOC_PM2R (IDENT_ADDR + 0x1A0000160UL)
-
-#define APECS_IOC_HAXR0 (IDENT_ADDR + 0x1A0000180UL)
-#define APECS_IOC_HAXR1 (IDENT_ADDR + 0x1A00001A0UL)
-#define APECS_IOC_HAXR2 (IDENT_ADDR + 0x1A00001C0UL)
-
-#define APECS_IOC_PMLT (IDENT_ADDR + 0x1A00001E0UL)
-
-#define APECS_IOC_TLBTAG0 (IDENT_ADDR + 0x1A0000200UL)
-#define APECS_IOC_TLBTAG1 (IDENT_ADDR + 0x1A0000220UL)
-#define APECS_IOC_TLBTAG2 (IDENT_ADDR + 0x1A0000240UL)
-#define APECS_IOC_TLBTAG3 (IDENT_ADDR + 0x1A0000260UL)
-#define APECS_IOC_TLBTAG4 (IDENT_ADDR + 0x1A0000280UL)
-#define APECS_IOC_TLBTAG5 (IDENT_ADDR + 0x1A00002A0UL)
-#define APECS_IOC_TLBTAG6 (IDENT_ADDR + 0x1A00002C0UL)
-#define APECS_IOC_TLBTAG7 (IDENT_ADDR + 0x1A00002E0UL)
-
-#define APECS_IOC_TLBDATA0 (IDENT_ADDR + 0x1A0000300UL)
-#define APECS_IOC_TLBDATA1 (IDENT_ADDR + 0x1A0000320UL)
-#define APECS_IOC_TLBDATA2 (IDENT_ADDR + 0x1A0000340UL)
-#define APECS_IOC_TLBDATA3 (IDENT_ADDR + 0x1A0000360UL)
-#define APECS_IOC_TLBDATA4 (IDENT_ADDR + 0x1A0000380UL)
-#define APECS_IOC_TLBDATA5 (IDENT_ADDR + 0x1A00003A0UL)
-#define APECS_IOC_TLBDATA6 (IDENT_ADDR + 0x1A00003C0UL)
-#define APECS_IOC_TLBDATA7 (IDENT_ADDR + 0x1A00003E0UL)
-
-#define APECS_IOC_TBIA (IDENT_ADDR + 0x1A0000400UL)
-
-
-/*
- * 21071-CA Control and Status registers.
- * These are used to program memory timing,
- * configure memory and initialise the B-Cache.
- */
-#define APECS_MEM_GCR (IDENT_ADDR + 0x180000000UL)
-#define APECS_MEM_EDSR (IDENT_ADDR + 0x180000040UL)
-#define APECS_MEM_TAR (IDENT_ADDR + 0x180000060UL)
-#define APECS_MEM_ELAR (IDENT_ADDR + 0x180000080UL)
-#define APECS_MEM_EHAR (IDENT_ADDR + 0x1800000a0UL)
-#define APECS_MEM_SFT_RST (IDENT_ADDR + 0x1800000c0UL)
-#define APECS_MEM_LDxLAR (IDENT_ADDR + 0x1800000e0UL)
-#define APECS_MEM_LDxHAR (IDENT_ADDR + 0x180000100UL)
-#define APECS_MEM_GTR (IDENT_ADDR + 0x180000200UL)
-#define APECS_MEM_RTR (IDENT_ADDR + 0x180000220UL)
-#define APECS_MEM_VFPR (IDENT_ADDR + 0x180000240UL)
-#define APECS_MEM_PDLDR (IDENT_ADDR + 0x180000260UL)
-#define APECS_MEM_PDhDR (IDENT_ADDR + 0x180000280UL)
-
-/* Bank x Base Address Register */
-#define APECS_MEM_B0BAR (IDENT_ADDR + 0x180000800UL)
-#define APECS_MEM_B1BAR (IDENT_ADDR + 0x180000820UL)
-#define APECS_MEM_B2BAR (IDENT_ADDR + 0x180000840UL)
-#define APECS_MEM_B3BAR (IDENT_ADDR + 0x180000860UL)
-#define APECS_MEM_B4BAR (IDENT_ADDR + 0x180000880UL)
-#define APECS_MEM_B5BAR (IDENT_ADDR + 0x1800008A0UL)
-#define APECS_MEM_B6BAR (IDENT_ADDR + 0x1800008C0UL)
-#define APECS_MEM_B7BAR (IDENT_ADDR + 0x1800008E0UL)
-#define APECS_MEM_B8BAR (IDENT_ADDR + 0x180000900UL)
-
-/* Bank x Configuration Register */
-#define APECS_MEM_B0BCR (IDENT_ADDR + 0x180000A00UL)
-#define APECS_MEM_B1BCR (IDENT_ADDR + 0x180000A20UL)
-#define APECS_MEM_B2BCR (IDENT_ADDR + 0x180000A40UL)
-#define APECS_MEM_B3BCR (IDENT_ADDR + 0x180000A60UL)
-#define APECS_MEM_B4BCR (IDENT_ADDR + 0x180000A80UL)
-#define APECS_MEM_B5BCR (IDENT_ADDR + 0x180000AA0UL)
-#define APECS_MEM_B6BCR (IDENT_ADDR + 0x180000AC0UL)
-#define APECS_MEM_B7BCR (IDENT_ADDR + 0x180000AE0UL)
-#define APECS_MEM_B8BCR (IDENT_ADDR + 0x180000B00UL)
-
-/* Bank x Timing Register A */
-#define APECS_MEM_B0TRA (IDENT_ADDR + 0x180000C00UL)
-#define APECS_MEM_B1TRA (IDENT_ADDR + 0x180000C20UL)
-#define APECS_MEM_B2TRA (IDENT_ADDR + 0x180000C40UL)
-#define APECS_MEM_B3TRA (IDENT_ADDR + 0x180000C60UL)
-#define APECS_MEM_B4TRA (IDENT_ADDR + 0x180000C80UL)
-#define APECS_MEM_B5TRA (IDENT_ADDR + 0x180000CA0UL)
-#define APECS_MEM_B6TRA (IDENT_ADDR + 0x180000CC0UL)
-#define APECS_MEM_B7TRA (IDENT_ADDR + 0x180000CE0UL)
-#define APECS_MEM_B8TRA (IDENT_ADDR + 0x180000D00UL)
-
-/* Bank x Timing Register B */
-#define APECS_MEM_B0TRB (IDENT_ADDR + 0x180000E00UL)
-#define APECS_MEM_B1TRB (IDENT_ADDR + 0x180000E20UL)
-#define APECS_MEM_B2TRB (IDENT_ADDR + 0x180000E40UL)
-#define APECS_MEM_B3TRB (IDENT_ADDR + 0x180000E60UL)
-#define APECS_MEM_B4TRB (IDENT_ADDR + 0x180000E80UL)
-#define APECS_MEM_B5TRB (IDENT_ADDR + 0x180000EA0UL)
-#define APECS_MEM_B6TRB (IDENT_ADDR + 0x180000EC0UL)
-#define APECS_MEM_B7TRB (IDENT_ADDR + 0x180000EE0UL)
-#define APECS_MEM_B8TRB (IDENT_ADDR + 0x180000F00UL)
-
-
-/*
- * Memory spaces:
- */
-#define APECS_IACK_SC (IDENT_ADDR + 0x1b0000000UL)
-#define APECS_CONF (IDENT_ADDR + 0x1e0000000UL)
-#define APECS_IO (IDENT_ADDR + 0x1c0000000UL)
-#define APECS_SPARSE_MEM (IDENT_ADDR + 0x200000000UL)
-#define APECS_DENSE_MEM (IDENT_ADDR + 0x300000000UL)
-#define DENSE_MEM(addr) APECS_DENSE_MEM
-
-/*
- * Bit definitions for I/O Controller status register 0:
- */
-#define APECS_IOC_STAT0_CMD 0xf
-#define APECS_IOC_STAT0_ERR (1<<4)
-#define APECS_IOC_STAT0_LOST (1<<5)
-#define APECS_IOC_STAT0_THIT (1<<6)
-#define APECS_IOC_STAT0_TREF (1<<7)
-#define APECS_IOC_STAT0_CODE_SHIFT 8
-#define APECS_IOC_STAT0_CODE_MASK 0x7
-#define APECS_IOC_STAT0_P_NBR_SHIFT 13
-#define APECS_IOC_STAT0_P_NBR_MASK 0x7ffff
-
-#define HAE_ADDRESS APECS_IOC_HAXR1
-
-#ifdef __KERNEL__
-
-/*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-/* NOTE: we fudge the window 1 maximum as 48Mb instead of 64Mb, to prevent
- virt_to_bus() from returning an address in the first window, for a
- data area that goes beyond the 64Mb first DMA window. Sigh...
- This MUST match with <asm/dma.h> MAX_DMA_ADDRESS for consistency, but
- we can't just use that here, because of header file looping... :-(
-*/
-extern inline unsigned long virt_to_bus(void * address)
-{
- unsigned long paddr = virt_to_phys(address);
-#ifdef CONFIG_ALPHA_XL
- if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID)
- return paddr + APECS_XL_DMA_WIN1_BASE;
- else
- return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */
-#else /* CONFIG_ALPHA_XL */
- return paddr + APECS_DMA_WIN_BASE;
-#endif /* CONFIG_ALPHA_XL */
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- /*
- * This check is a sanity check but also ensures that bus
- * address 0 maps to virtual address 0 which is useful to
- * detect null "pointers" (the NCR driver is much simpler if
- * NULL pointers are preserved).
- */
-#ifdef CONFIG_ALPHA_XL
- if (address < APECS_XL_DMA_WIN1_BASE)
- return 0;
- else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
- return phys_to_virt(address - APECS_XL_DMA_WIN1_BASE);
- else /* should be more checking here, maybe? */
- return phys_to_virt(address - APECS_XL_DMA_WIN2_BASE);
-#else /* CONFIG_ALPHA_XL */
- if (address < APECS_DMA_WIN_BASE)
- return 0;
- return phys_to_virt(address - APECS_DMA_WIN_BASE);
-#endif /* CONFIG_ALPHA_XL */
-}
-
-/*
- * I/O functions:
- *
- * Unlike Jensen, the APECS machines have no concept of local
- * I/O---everything goes over the PCI bus.
- *
- * There is plenty room for optimization here. In particular,
- * the Alpha's insb/insw/extb/extw should be useful in moving
- * data to/from the right byte-lanes.
- */
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + APECS_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + APECS_IO + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip) ((addr << 5) + APECS_IO + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
- mb();
-}
-
-
-/*
- * Memory functions. 64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, msb;
-
- shift = (addr & 0x3) * 8;
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- result = *(vuip) ((addr << 5) + APECS_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;
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
- result >>= shift;
- return 0xffffUL & result;
-}
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip) (addr + APECS_DENSE_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp) (addr + APECS_DENSE_MEM);
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long msb;
-
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long msb;
-
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip) (addr + APECS_DENSE_MEM) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp) (addr + APECS_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 readq(a) __readq((unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vuip
-#undef vulp
-
-extern unsigned long apecs_init (unsigned long mem_start,
- unsigned long mem_end);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling APECS machine checks:
- */
-#ifdef CONFIG_ALPHA_MIKASA
-struct el_apecs_sysdata_mcheck {
- unsigned long coma_gcr;
- unsigned long coma_edsr;
- unsigned long coma_ter;
- unsigned long coma_elar;
- unsigned long coma_ehar;
- unsigned long coma_ldlr;
- unsigned long coma_ldhr;
- unsigned long coma_base0;
- unsigned long coma_base1;
- unsigned long coma_base2;
- unsigned long coma_base3;
- unsigned long coma_cnfg0;
- unsigned long coma_cnfg1;
- unsigned long coma_cnfg2;
- unsigned long coma_cnfg3;
- unsigned long epic_dcsr;
- unsigned long epic_pear;
- unsigned long epic_sear;
- unsigned long epic_tbr1;
- unsigned long epic_tbr2;
- unsigned long epic_pbr1;
- unsigned long epic_pbr2;
- unsigned long epic_pmr1;
- unsigned long epic_pmr2;
- unsigned long epic_harx1;
- unsigned long epic_harx2;
- unsigned long epic_pmlt;
- unsigned long epic_tag0;
- unsigned long epic_tag1;
- unsigned long epic_tag2;
- unsigned long epic_tag3;
- unsigned long epic_tag4;
- unsigned long epic_tag5;
- unsigned long epic_tag6;
- unsigned long epic_tag7;
- unsigned long epic_data0;
- unsigned long epic_data1;
- unsigned long epic_data2;
- unsigned long epic_data3;
- unsigned long epic_data4;
- unsigned long epic_data5;
- unsigned long epic_data6;
- unsigned long epic_data7;
-
- unsigned long pceb_vid;
- unsigned long pceb_did;
- unsigned long pceb_revision;
- unsigned long pceb_command;
- unsigned long pceb_status;
- unsigned long pceb_latency;
- unsigned long pceb_control;
- unsigned long pceb_arbcon;
- unsigned long pceb_arbpri;
-
- unsigned long esc_id;
- unsigned long esc_revision;
- unsigned long esc_int0;
- unsigned long esc_int1;
- unsigned long esc_elcr0;
- unsigned long esc_elcr1;
- unsigned long esc_last_eisa;
- unsigned long esc_nmi_stat;
-
- unsigned long pci_ir;
- unsigned long pci_imr;
- unsigned long svr_mgr;
-};
-#else /* CONFIG_ALPHA_MIKASA */
-/* this for the normal APECS machines */
-struct el_apecs_sysdata_mcheck {
- unsigned long coma_gcr;
- unsigned long coma_edsr;
- unsigned long coma_ter;
- unsigned long coma_elar;
- unsigned long coma_ehar;
- unsigned long coma_ldlr;
- unsigned long coma_ldhr;
- unsigned long coma_base0;
- unsigned long coma_base1;
- unsigned long coma_base2;
- unsigned long coma_cnfg0;
- unsigned long coma_cnfg1;
- unsigned long coma_cnfg2;
- unsigned long epic_dcsr;
- unsigned long epic_pear;
- unsigned long epic_sear;
- unsigned long epic_tbr1;
- unsigned long epic_tbr2;
- unsigned long epic_pbr1;
- unsigned long epic_pbr2;
- unsigned long epic_pmr1;
- unsigned long epic_pmr2;
- unsigned long epic_harx1;
- unsigned long epic_harx2;
- unsigned long epic_pmlt;
- unsigned long epic_tag0;
- unsigned long epic_tag1;
- unsigned long epic_tag2;
- unsigned long epic_tag3;
- unsigned long epic_tag4;
- unsigned long epic_tag5;
- unsigned long epic_tag6;
- unsigned long epic_tag7;
- unsigned long epic_data0;
- unsigned long epic_data1;
- unsigned long epic_data2;
- unsigned long epic_data3;
- unsigned long epic_data4;
- unsigned long epic_data5;
- unsigned long epic_data6;
- unsigned long epic_data7;
-};
-#endif /* CONFIG_ALPHA_MIKASA */
-
-struct el_procdata {
- unsigned long paltemp[32]; /* PAL TEMP REGS. */
- /* EV4-specific fields */
- unsigned long exc_addr; /* Address of excepting instruction. */
- unsigned long exc_sum; /* Summary of arithmetic traps. */
- unsigned long exc_mask; /* Exception mask (from exc_sum). */
- unsigned long iccsr; /* IBox hardware enables. */
- unsigned long pal_base; /* Base address for PALcode. */
- unsigned long hier; /* Hardware Interrupt Enable. */
- unsigned long hirr; /* Hardware Interrupt Request. */
- unsigned long csr; /* D-stream fault info. */
- unsigned long dc_stat; /* D-cache status (ECC/Parity Err). */
- unsigned long dc_addr; /* EV3 Phys Addr for ECC/DPERR. */
- unsigned long abox_ctl; /* ABox Control Register. */
- unsigned long biu_stat; /* BIU Status. */
- unsigned long biu_addr; /* BUI Address. */
- unsigned long biu_ctl; /* BIU Control. */
- unsigned long fill_syndrome;/* For correcting ECC errors. */
- unsigned long fill_addr; /* Cache block which was being read */
- unsigned long va; /* Effective VA of fault or miss. */
- unsigned long bc_tag; /* Backup Cache Tag Probe Results.*/
-};
-
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_APECS__H__ */
__asm__ __volatile__(
"1: ldl_l %0,%1\n"
- " and %0,%3,%2\n\t"
- " beq %2,2f\n\t"
- " xor %0,%3,%0\n\t"
- " stl_c %0,%1\n\t"
+ " and %0,%3,%2\n"
+ " beq %2,2f\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
" beq %0,3f\n"
"2:\n"
".section .text2,\"ax\"\n"
__asm__ __volatile__(
"1: ldl_l %0,%1\n"
- " xor %0,%2,%0\n\t"
- " stl_c %0,%1\n\t"
+ " xor %0,%2,%0\n"
+ " stl_c %0,%1\n"
" beq %0,3f\n"
".section .text2,\"ax\"\n"
"3: br 1b\n"
__asm__ __volatile__(
"1: ldl_l %0,%1\n"
- " and %0,%3,%2\n\t"
- " beq %2,2f\n\t"
- " xor %0,%3,%0\n\t"
- " stl_c %0,%1\n\t"
+ " and %0,%3,%2\n"
+ " beq %2,2f\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
" beq %0,3f\n"
"2:\n"
".section .text2,\"ax\"\n"
__asm__ __volatile__(
"1: ldl_l %0,%1\n"
- " and %0,%3,%2\n\t"
- " xor %0,%3,%0\n\t"
- " stl_c %0,%1\n\t"
+ " and %0,%3,%2\n"
+ " xor %0,%3,%0\n"
+ " stl_c %0,%1\n"
" beq %0,3f\n"
".section .text2,\"ax\"\n"
"3: br 1b\n"
extern inline unsigned long ffz(unsigned long word)
{
+#ifdef __alpha_cix__
+ /* Whee. EV6 can calculate it directly. */
+ unsigned long result;
+ __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word));
+#else
unsigned long bits, qofs, bofs;
__asm__("cmpbge %1,%2,%0" : "=r"(bits) : "r"(word), "r"(~0UL));
bofs = ffz_b(bits);
return qofs*8 + bofs;
+#endif
}
#ifdef __KERNEL__
* differs in spirit from the above ffz (man ffs).
*/
-#define ffs(x) generic_ffs(x)
+extern inline int ffs(int word)
+{
+ int result = ffz(~word);
+ return word ? result+1 : 0;
+}
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
+#ifdef __alpha_cix__
+/* Whee. EV6 can calculate it directly. */
+extern __inline__ unsigned long hweight64(unsigned long w)
+{
+ unsigned long result;
+ __asm__("ctpop %1,%0" : "=r"(result) : "r"(w));
+ return result;
+}
+
+#define hweight32(x) hweight64((x) & 0xfffffffful)
+#define hweight16(x) hweight64((x) & 0xfffful)
+#define hweight8(x) hweight64((x) & 0xfful)
+#else
#define hweight32(x) generic_hweight32(x)
#define hweight16(x) generic_hweight16(x)
-#define hweight8(x) generic_hweight8(x)
+#define hweight8(x) generic_hweight8(x)
+#endif
#endif /* __KERNEL__ */
+++ /dev/null
-#ifndef __ALPHA_CIA__H__
-#define __ALPHA_CIA__H__
-
-#include <linux/config.h>
-#include <linux/types.h>
-
-/*
- * CIA 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 **
-** **
-**------------------------------------------------------------------------*/
-
-
-/* CIA 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_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
-#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
-#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define CIA_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define CIA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int CIA_DMA_WIN_BASE;
-extern unsigned int CIA_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define CIA_DMA_WIN_BASE (1024*1024*1024)
-#define CIA_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-/*
- * 21171-CA Control and Status Registers (p4-1)
- */
-#define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL)
-#define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
-#define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL)
-#define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL)
-#define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
-#define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL)
-#define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL)
-#define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL)
-
-/*
- * 21171-CA Diagnostic Registers (p4-2)
- */
-#define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL)
-#define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
-
-/*
- * 21171-CA Performance Monitor registers (p4-3)
- */
-#define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
-#define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
-
-/*
- * 21171-CA Error registers (p4-3)
- */
-#define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL)
-#define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL)
-#define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL)
-#define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL)
-#define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
-#define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL)
-#define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL)
-#define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL)
-#define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
-#define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
-#define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL)
-
-/*
- * 2117A-CA PCI Address Translation Registers.
- */
-#define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL)
-
-#define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL)
-#define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL)
-#define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL)
-
-#define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL)
-#define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL)
-#define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL)
-
-#define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL)
-#define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL)
-#define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL)
-
-#define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL)
-#define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL)
-#define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL)
-
-/*
- * 21171-CA System configuration registers (p4-3)
- */
-#define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL)
-#define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL)
-#define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL)
-#define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL)
-#define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL)
-#define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL)
-#define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL)
-#define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL)
-#define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL)
-#define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL)
-#define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL)
-#define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL)
-
-/*
- * Memory spaces:
- */
-#define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL)
-#define CIA_CONF (IDENT_ADDR + 0x8700000000UL)
-#define CIA_IO (IDENT_ADDR + 0x8580000000UL)
-#define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
-#define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL)
-#define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL)
-#define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
-#define DENSE_MEM(addr) CIA_DENSE_MEM
-
-/*
- * ALCOR's GRU ASIC registers
- */
-#define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL)
-#define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL)
-#define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL)
-#define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL)
-#define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL)
-
-#define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL)
-#define GRU_SCR (IDENT_ADDR + 0x8780000300UL)
-#define GRU_LED (IDENT_ADDR + 0x8780000800UL)
-#define GRU_RESET (IDENT_ADDR + 0x8780000900UL)
-
-#if defined(CONFIG_ALPHA_ALCOR)
-#define GRU_INT_REQ_BITS 0x800fffffUL
-#elif defined(CONFIG_ALPHA_XLT)
-#define GRU_INT_REQ_BITS 0x80003fffUL
-#else
-#define GRU_INT_REQ_BITS 0xffffffffUL
-#endif
-
-/*
- * Bit definitions for I/O Controller status register 0:
- */
-#define CIA_IOC_STAT0_CMD 0xf
-#define CIA_IOC_STAT0_ERR (1<<4)
-#define CIA_IOC_STAT0_LOST (1<<5)
-#define CIA_IOC_STAT0_THIT (1<<6)
-#define CIA_IOC_STAT0_TREF (1<<7)
-#define CIA_IOC_STAT0_CODE_SHIFT 8
-#define CIA_IOC_STAT0_CODE_MASK 0x7
-#define CIA_IOC_STAT0_P_NBR_SHIFT 13
-#define CIA_IOC_STAT0_P_NBR_MASK 0x7ffff
-
-#define HAE_ADDRESS CIA_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) + CIA_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address - CIA_DMA_WIN_BASE);
-}
-
-/*
- * I/O functions:
- *
- * CIA (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 *
-#define vulp volatile unsigned long *
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + CIA_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + CIA_IO + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip) ((addr << 5) + CIA_IO + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip) ((addr << 5) + CIA_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
- *
- */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-
-extern unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3;
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= cia_sm_base_r1) &&
- (addr <= (cia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= cia_sm_base_r2) &&
- (addr <= (cia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= cia_sm_base_r3) &&
- (addr <= (cia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__readb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffUL & result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= cia_sm_base_r1) &&
- (addr <= (cia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x08);
- else
- if ((addr >= cia_sm_base_r2) &&
- (addr <= (cia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x08);
- else
- if ((addr >= cia_sm_base_r3) &&
- (addr <= (cia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x08);
- else
- {
-#if 0
- printk("__readw: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= cia_sm_base_r1) &&
- (addr <= (cia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= cia_sm_base_r2) &&
- (addr <= (cia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= cia_sm_base_r3) &&
- (addr <= (cia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writeb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= cia_sm_base_r1) &&
- (addr <= (cia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= cia_sm_base_r2) &&
- (addr <= (cia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= cia_sm_base_r3) &&
- (addr <= (cia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writew: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x00010001;
-}
-
-#else /* SRM_SETUP */
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, msb;
-
- shift = (addr & 0x3) * 8 ;
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- result = *(vuip) ((addr << 5) + CIA_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_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- result = *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
- result >>= shift;
- return 0xffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = b * 0x00010001;
-}
-
-#endif /* SRM_SETUP */
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip) (addr + CIA_DENSE_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp) (addr + CIA_DENSE_MEM);
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip) (addr + CIA_DENSE_MEM) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp) (addr + CIA_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 readq(a) __readq((unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vuip
-#undef vulp
-
-extern unsigned long cia_init (unsigned long mem_start,
- unsigned long mem_end);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling CIA machine checks:
- */
-/* ev5-specific info: */
-struct el_procdata {
- unsigned long shadow[8]; /* PALmode shadow registers */
- unsigned long paltemp[24]; /* PAL temporary registers */
- /* EV5-specific fields */
- unsigned long exc_addr; /* Address of excepting instruction. */
- unsigned long exc_sum; /* Summary of arithmetic traps. */
- unsigned long exc_mask; /* Exception mask (from exc_sum). */
- unsigned long exc_base; /* PALbase at time of exception. */
- unsigned long isr; /* Interrupt summary register. */
- unsigned long icsr; /* Ibox control register. */
- unsigned long ic_perr_stat;
- unsigned long dc_perr_stat;
- unsigned long va; /* Effective VA of fault or miss. */
- unsigned long mm_stat;
- unsigned long sc_addr;
- unsigned long sc_stat;
- unsigned long bc_tag_addr;
- unsigned long ei_addr;
- unsigned long fill_syn;
- unsigned long ei_stat;
- unsigned long ld_lock;
-};
-
-/* system-specific info: */
-struct el_CIA_sysdata_mcheck {
- unsigned long coma_gcr;
- unsigned long coma_edsr;
- unsigned long coma_ter;
- unsigned long coma_elar;
- unsigned long coma_ehar;
- unsigned long coma_ldlr;
- unsigned long coma_ldhr;
- unsigned long coma_base0;
- unsigned long coma_base1;
- unsigned long coma_base2;
- unsigned long coma_cnfg0;
- unsigned long coma_cnfg1;
- unsigned long coma_cnfg2;
- unsigned long epic_dcsr;
- unsigned long epic_pear;
- unsigned long epic_sear;
- unsigned long epic_tbr1;
- unsigned long epic_tbr2;
- unsigned long epic_pbr1;
- unsigned long epic_pbr2;
- unsigned long epic_pmr1;
- unsigned long epic_pmr2;
- unsigned long epic_harx1;
- unsigned long epic_harx2;
- unsigned long epic_pmlt;
- unsigned long epic_tag0;
- unsigned long epic_tag1;
- unsigned long epic_tag2;
- unsigned long epic_tag3;
- unsigned long epic_tag4;
- unsigned long epic_tag5;
- unsigned long epic_tag6;
- unsigned long epic_tag7;
- unsigned long epic_data0;
- unsigned long epic_data1;
- unsigned long epic_data2;
- unsigned long epic_data3;
- unsigned long epic_data4;
- unsigned long epic_data5;
- unsigned long epic_data6;
- unsigned long epic_data7;
-};
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_CIA__H__ */
--- /dev/null
+#ifndef __ALPHA_COMPILER_H
+#define __ALPHA_COMPILER_H
+
+/*
+ * Herein are macros we use when describing various patterns we want to GCC.
+ * In all cases we can get better schedules out of the compiler if we hide
+ * as little as possible inside inline assembly. However, we want to be
+ * able to know what we'll get out before giving up inline assembly. Thus
+ * these tests and macros.
+ */
+
+/*
+ * EGCS (of varying versions) does a good job of using insxl and extxl.
+ */
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
+#define __kernel_insbl(val, shift) \
+ (((unsigned long)(val) & 0xfful) << ((shift) * 8))
+#define __kernel_inswl(val, shift) \
+ (((unsigned long)(val) & 0xfffful) << ((shift) * 8))
+#else
+#define __kernel_insbl(val, shift) \
+ ({ unsigned long __kir; \
+ __asm__("insbl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \
+ __kir; })
+#define __kernel_inswl(val, shift) \
+ ({ unsigned long __kir; \
+ __asm__("inswl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \
+ __kir; })
+#endif
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 92
+#define __kernel_extbl(val, shift) (((val) >> (((shift) & 7) * 8)) & 0xfful)
+#define __kernel_extwl(val, shift) (((val) >> (((shift) & 7) * 8)) & 0xfffful)
+#else
+#define __kernel_extbl(val, shift) \
+ ({ unsigned long __kir; \
+ __asm__("extbl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \
+ __kir; })
+#define __kernel_extwl(val, shift) \
+ ({ unsigned long __kir; \
+ __asm__("extwl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \
+ __kir; })
+#endif
+
+
+/*
+ * Beginning with EGCS 1.1, GCC defines __alpha_bwx__ when the BWX
+ * extension is enabled. Previous versions did not define anything
+ * we could test during compilation, so allow users to tell us when
+ * the compiler will DTRT.
+ */
+
+#if defined(HAVE_BWX) || defined(__alpha_bwx__)
+#define __kernel_ldbu(mem) (mem)
+#define __kernel_ldwu(mem) (mem)
+#define __kernel_stb(val,mem) ((mem) = (val))
+#define __kernel_stw(val,mem) ((mem) = (val))
+#else
+#define __kernel_ldbu(mem) \
+ ({ unsigned char __kir; \
+ __asm__("ldbu %0,%1" : "=r"(__kir) : "m"(mem)); \
+ __kir; })
+#define __kernel_ldwu(mem) \
+ ({ unsigned short __kir; \
+ __asm__("ldwu %0,%1" : "=r"(__kir) : "m"(mem)); \
+ __kir; })
+#define __kernel_stb(val,mem) \
+ __asm__("stb %1,%0" : "=m"(mem) : "r"(val))
+#define __kernel_stw(val,mem) \
+ __asm__("stw %1,%0" : "=m"(mem) : "r"(val))
+#endif
+
+#endif /* __ALPHA_COMPILER_H */
--- /dev/null
+#ifndef __ALPHA_APECS__H__
+#define __ALPHA_APECS__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+/*
+ * APECS is the internal name for the 2107x chipset which provides
+ * memory controller and PCI access for the 21064 chip based systems.
+ *
+ * This file is based on:
+ *
+ * DECchip 21071-AA and DECchip 21072-AA Core Logic Chipsets
+ * Data Sheet
+ *
+ * EC-N0648-72
+ *
+ *
+ * david.rusling@reo.mts.dec.com Initial Version.
+ *
+ */
+
+/*
+ An AVANTI *might* be an XL, and an XL has only 27 bits of ISA address
+ that get passed through the PCI<->ISA bridge chip. So we've gotta use
+ both windows to max out the physical memory we can DMA to. Sigh...
+
+ If we try a window at 0 for 1GB as a work-around, we run into conflicts
+ with ISA/PCI bus memory which can't be relocated, like VGA aperture and
+ BIOS ROMs. So we must put the windows high enough to avoid these areas.
+
+ We put window 1 at BUS 64Mb for 64Mb, mapping physical 0 to 64Mb-1,
+ and window 2 at BUS 1Gb for 1Gb, mapping physical 0 to 1Gb-1.
+ Yes, this does map 0 to 64Mb-1 twice, but only window 1 will actually
+ be used for that range (via virt_to_bus()).
+
+ Note that we actually fudge the window 1 maximum as 48Mb instead of 64Mb,
+ to keep virt_to_bus() from returning an address in the first window, for
+ a data area that goes beyond the 64Mb first DMA window. Sigh...
+ The fudge factor MUST match with <asm/dma.h> MAX_DMA_ADDRESS, but
+ we can't just use that here, because of header file looping... :-(
+
+ Window 1 will be used for all DMA from the ISA bus; yes, that does
+ limit what memory an ISA floppy or sound card or Ethernet can touch, but
+ it's also a known limitation on other platforms as well. We use the
+ same technique that is used on INTEL platforms with similar limitation:
+ set MAX_DMA_ADDRESS and clear some pages' DMAable flags during mem_init().
+ We trust that any ISA bus device drivers will *always* ask for DMAable
+ memory explicitly via kmalloc()/get_free_pages() flags arguments.
+
+ Note that most PCI bus devices' drivers do *not* explicitly ask for
+ DMAable memory; they count on being able to DMA to any memory they
+ get from kmalloc()/get_free_pages(). They will also use window 1 for
+ any physical memory accesses below 64Mb; the rest will be handled by
+ window 2, maxing out at 1Gb of memory. I trust this is enough... :-)
+
+ We hope that the area before the first window is large enough so that
+ there will be no overlap at the top end (64Mb). We *must* locate the
+ PCI cards' memory just below window 1, so that there's still the
+ possibility of being able to access it via SPARSE space. This is
+ important for cards such as the Matrox Millennium, whose Xserver
+ wants to access memory-mapped registers in byte and short lengths.
+
+ Note that the XL is treated differently from the AVANTI, even though
+ for most other things they are identical. It didn't seem reasonable to
+ make the AVANTI support pay for the limitations of the XL. It is true,
+ however, that an XL kernel will run on an AVANTI without problems.
+*/
+#define APECS_XL_DMA_WIN1_BASE (64*1024*1024)
+#define APECS_XL_DMA_WIN1_SIZE (64*1024*1024)
+#define APECS_XL_DMA_WIN1_SIZE_PARANOID (48*1024*1024)
+#define APECS_XL_DMA_WIN2_BASE (1024*1024*1024)
+#define APECS_XL_DMA_WIN2_SIZE (1024*1024*1024)
+
+
+/* These are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64. */
+
+#define APECS_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define APECS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define APECS_DMA_WIN_BASE alpha_mv.dma_win_base
+#define APECS_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define APECS_DMA_WIN_BASE APECS_DMA_WIN_BASE_DEFAULT
+#define APECS_DMA_WIN_SIZE APECS_DMA_WIN_SIZE_DEFAULT
+#endif
+
+
+/*
+ * 21071-DA Control and Status registers.
+ * These are used for PCI memory access.
+ */
+#define APECS_IOC_DCSR (IDENT_ADDR + 0x1A0000000UL)
+#define APECS_IOC_PEAR (IDENT_ADDR + 0x1A0000020UL)
+#define APECS_IOC_SEAR (IDENT_ADDR + 0x1A0000040UL)
+#define APECS_IOC_DR1 (IDENT_ADDR + 0x1A0000060UL)
+#define APECS_IOC_DR2 (IDENT_ADDR + 0x1A0000080UL)
+#define APECS_IOC_DR3 (IDENT_ADDR + 0x1A00000A0UL)
+
+#define APECS_IOC_TB1R (IDENT_ADDR + 0x1A00000C0UL)
+#define APECS_IOC_TB2R (IDENT_ADDR + 0x1A00000E0UL)
+
+#define APECS_IOC_PB1R (IDENT_ADDR + 0x1A0000100UL)
+#define APECS_IOC_PB2R (IDENT_ADDR + 0x1A0000120UL)
+
+#define APECS_IOC_PM1R (IDENT_ADDR + 0x1A0000140UL)
+#define APECS_IOC_PM2R (IDENT_ADDR + 0x1A0000160UL)
+
+#define APECS_IOC_HAXR0 (IDENT_ADDR + 0x1A0000180UL)
+#define APECS_IOC_HAXR1 (IDENT_ADDR + 0x1A00001A0UL)
+#define APECS_IOC_HAXR2 (IDENT_ADDR + 0x1A00001C0UL)
+
+#define APECS_IOC_PMLT (IDENT_ADDR + 0x1A00001E0UL)
+
+#define APECS_IOC_TLBTAG0 (IDENT_ADDR + 0x1A0000200UL)
+#define APECS_IOC_TLBTAG1 (IDENT_ADDR + 0x1A0000220UL)
+#define APECS_IOC_TLBTAG2 (IDENT_ADDR + 0x1A0000240UL)
+#define APECS_IOC_TLBTAG3 (IDENT_ADDR + 0x1A0000260UL)
+#define APECS_IOC_TLBTAG4 (IDENT_ADDR + 0x1A0000280UL)
+#define APECS_IOC_TLBTAG5 (IDENT_ADDR + 0x1A00002A0UL)
+#define APECS_IOC_TLBTAG6 (IDENT_ADDR + 0x1A00002C0UL)
+#define APECS_IOC_TLBTAG7 (IDENT_ADDR + 0x1A00002E0UL)
+
+#define APECS_IOC_TLBDATA0 (IDENT_ADDR + 0x1A0000300UL)
+#define APECS_IOC_TLBDATA1 (IDENT_ADDR + 0x1A0000320UL)
+#define APECS_IOC_TLBDATA2 (IDENT_ADDR + 0x1A0000340UL)
+#define APECS_IOC_TLBDATA3 (IDENT_ADDR + 0x1A0000360UL)
+#define APECS_IOC_TLBDATA4 (IDENT_ADDR + 0x1A0000380UL)
+#define APECS_IOC_TLBDATA5 (IDENT_ADDR + 0x1A00003A0UL)
+#define APECS_IOC_TLBDATA6 (IDENT_ADDR + 0x1A00003C0UL)
+#define APECS_IOC_TLBDATA7 (IDENT_ADDR + 0x1A00003E0UL)
+
+#define APECS_IOC_TBIA (IDENT_ADDR + 0x1A0000400UL)
+
+
+/*
+ * 21071-CA Control and Status registers.
+ * These are used to program memory timing,
+ * configure memory and initialise the B-Cache.
+ */
+#define APECS_MEM_GCR (IDENT_ADDR + 0x180000000UL)
+#define APECS_MEM_EDSR (IDENT_ADDR + 0x180000040UL)
+#define APECS_MEM_TAR (IDENT_ADDR + 0x180000060UL)
+#define APECS_MEM_ELAR (IDENT_ADDR + 0x180000080UL)
+#define APECS_MEM_EHAR (IDENT_ADDR + 0x1800000a0UL)
+#define APECS_MEM_SFT_RST (IDENT_ADDR + 0x1800000c0UL)
+#define APECS_MEM_LDxLAR (IDENT_ADDR + 0x1800000e0UL)
+#define APECS_MEM_LDxHAR (IDENT_ADDR + 0x180000100UL)
+#define APECS_MEM_GTR (IDENT_ADDR + 0x180000200UL)
+#define APECS_MEM_RTR (IDENT_ADDR + 0x180000220UL)
+#define APECS_MEM_VFPR (IDENT_ADDR + 0x180000240UL)
+#define APECS_MEM_PDLDR (IDENT_ADDR + 0x180000260UL)
+#define APECS_MEM_PDhDR (IDENT_ADDR + 0x180000280UL)
+
+/* Bank x Base Address Register */
+#define APECS_MEM_B0BAR (IDENT_ADDR + 0x180000800UL)
+#define APECS_MEM_B1BAR (IDENT_ADDR + 0x180000820UL)
+#define APECS_MEM_B2BAR (IDENT_ADDR + 0x180000840UL)
+#define APECS_MEM_B3BAR (IDENT_ADDR + 0x180000860UL)
+#define APECS_MEM_B4BAR (IDENT_ADDR + 0x180000880UL)
+#define APECS_MEM_B5BAR (IDENT_ADDR + 0x1800008A0UL)
+#define APECS_MEM_B6BAR (IDENT_ADDR + 0x1800008C0UL)
+#define APECS_MEM_B7BAR (IDENT_ADDR + 0x1800008E0UL)
+#define APECS_MEM_B8BAR (IDENT_ADDR + 0x180000900UL)
+
+/* Bank x Configuration Register */
+#define APECS_MEM_B0BCR (IDENT_ADDR + 0x180000A00UL)
+#define APECS_MEM_B1BCR (IDENT_ADDR + 0x180000A20UL)
+#define APECS_MEM_B2BCR (IDENT_ADDR + 0x180000A40UL)
+#define APECS_MEM_B3BCR (IDENT_ADDR + 0x180000A60UL)
+#define APECS_MEM_B4BCR (IDENT_ADDR + 0x180000A80UL)
+#define APECS_MEM_B5BCR (IDENT_ADDR + 0x180000AA0UL)
+#define APECS_MEM_B6BCR (IDENT_ADDR + 0x180000AC0UL)
+#define APECS_MEM_B7BCR (IDENT_ADDR + 0x180000AE0UL)
+#define APECS_MEM_B8BCR (IDENT_ADDR + 0x180000B00UL)
+
+/* Bank x Timing Register A */
+#define APECS_MEM_B0TRA (IDENT_ADDR + 0x180000C00UL)
+#define APECS_MEM_B1TRA (IDENT_ADDR + 0x180000C20UL)
+#define APECS_MEM_B2TRA (IDENT_ADDR + 0x180000C40UL)
+#define APECS_MEM_B3TRA (IDENT_ADDR + 0x180000C60UL)
+#define APECS_MEM_B4TRA (IDENT_ADDR + 0x180000C80UL)
+#define APECS_MEM_B5TRA (IDENT_ADDR + 0x180000CA0UL)
+#define APECS_MEM_B6TRA (IDENT_ADDR + 0x180000CC0UL)
+#define APECS_MEM_B7TRA (IDENT_ADDR + 0x180000CE0UL)
+#define APECS_MEM_B8TRA (IDENT_ADDR + 0x180000D00UL)
+
+/* Bank x Timing Register B */
+#define APECS_MEM_B0TRB (IDENT_ADDR + 0x180000E00UL)
+#define APECS_MEM_B1TRB (IDENT_ADDR + 0x180000E20UL)
+#define APECS_MEM_B2TRB (IDENT_ADDR + 0x180000E40UL)
+#define APECS_MEM_B3TRB (IDENT_ADDR + 0x180000E60UL)
+#define APECS_MEM_B4TRB (IDENT_ADDR + 0x180000E80UL)
+#define APECS_MEM_B5TRB (IDENT_ADDR + 0x180000EA0UL)
+#define APECS_MEM_B6TRB (IDENT_ADDR + 0x180000EC0UL)
+#define APECS_MEM_B7TRB (IDENT_ADDR + 0x180000EE0UL)
+#define APECS_MEM_B8TRB (IDENT_ADDR + 0x180000F00UL)
+
+
+/*
+ * Memory spaces:
+ */
+#define APECS_IACK_SC (IDENT_ADDR + 0x1b0000000UL)
+#define APECS_CONF (IDENT_ADDR + 0x1e0000000UL)
+#define APECS_IO (IDENT_ADDR + 0x1c0000000UL)
+#define APECS_SPARSE_MEM (IDENT_ADDR + 0x200000000UL)
+#define APECS_DENSE_MEM (IDENT_ADDR + 0x300000000UL)
+
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define APECS_IOC_STAT0_CMD 0xf
+#define APECS_IOC_STAT0_ERR (1<<4)
+#define APECS_IOC_STAT0_LOST (1<<5)
+#define APECS_IOC_STAT0_THIT (1<<6)
+#define APECS_IOC_STAT0_TREF (1<<7)
+#define APECS_IOC_STAT0_CODE_SHIFT 8
+#define APECS_IOC_STAT0_CODE_MASK 0x7
+#define APECS_IOC_STAT0_P_NBR_SHIFT 13
+#define APECS_IOC_STAT0_P_NBR_MASK 0x7ffff
+
+#define APECS_HAE_ADDRESS APECS_IOC_HAXR1
+
+
+/*
+ * Data structure for handling APECS machine checks:
+ */
+
+struct el_apecs_mikasa_sysdata_mcheck
+{
+ unsigned long coma_gcr;
+ unsigned long coma_edsr;
+ unsigned long coma_ter;
+ unsigned long coma_elar;
+ unsigned long coma_ehar;
+ unsigned long coma_ldlr;
+ unsigned long coma_ldhr;
+ unsigned long coma_base0;
+ unsigned long coma_base1;
+ unsigned long coma_base2;
+ unsigned long coma_base3;
+ unsigned long coma_cnfg0;
+ unsigned long coma_cnfg1;
+ unsigned long coma_cnfg2;
+ unsigned long coma_cnfg3;
+ unsigned long epic_dcsr;
+ unsigned long epic_pear;
+ unsigned long epic_sear;
+ unsigned long epic_tbr1;
+ unsigned long epic_tbr2;
+ unsigned long epic_pbr1;
+ unsigned long epic_pbr2;
+ unsigned long epic_pmr1;
+ unsigned long epic_pmr2;
+ unsigned long epic_harx1;
+ unsigned long epic_harx2;
+ unsigned long epic_pmlt;
+ unsigned long epic_tag0;
+ unsigned long epic_tag1;
+ unsigned long epic_tag2;
+ unsigned long epic_tag3;
+ unsigned long epic_tag4;
+ unsigned long epic_tag5;
+ unsigned long epic_tag6;
+ unsigned long epic_tag7;
+ unsigned long epic_data0;
+ unsigned long epic_data1;
+ unsigned long epic_data2;
+ unsigned long epic_data3;
+ unsigned long epic_data4;
+ unsigned long epic_data5;
+ unsigned long epic_data6;
+ unsigned long epic_data7;
+
+ unsigned long pceb_vid;
+ unsigned long pceb_did;
+ unsigned long pceb_revision;
+ unsigned long pceb_command;
+ unsigned long pceb_status;
+ unsigned long pceb_latency;
+ unsigned long pceb_control;
+ unsigned long pceb_arbcon;
+ unsigned long pceb_arbpri;
+
+ unsigned long esc_id;
+ unsigned long esc_revision;
+ unsigned long esc_int0;
+ unsigned long esc_int1;
+ unsigned long esc_elcr0;
+ unsigned long esc_elcr1;
+ unsigned long esc_last_eisa;
+ unsigned long esc_nmi_stat;
+
+ unsigned long pci_ir;
+ unsigned long pci_imr;
+ unsigned long svr_mgr;
+};
+
+/* This for the normal APECS machines. */
+struct el_apecs_sysdata_mcheck
+{
+ unsigned long coma_gcr;
+ unsigned long coma_edsr;
+ unsigned long coma_ter;
+ unsigned long coma_elar;
+ unsigned long coma_ehar;
+ unsigned long coma_ldlr;
+ unsigned long coma_ldhr;
+ unsigned long coma_base0;
+ unsigned long coma_base1;
+ unsigned long coma_base2;
+ unsigned long coma_cnfg0;
+ unsigned long coma_cnfg1;
+ unsigned long coma_cnfg2;
+ unsigned long epic_dcsr;
+ unsigned long epic_pear;
+ unsigned long epic_sear;
+ unsigned long epic_tbr1;
+ unsigned long epic_tbr2;
+ unsigned long epic_pbr1;
+ unsigned long epic_pbr2;
+ unsigned long epic_pmr1;
+ unsigned long epic_pmr2;
+ unsigned long epic_harx1;
+ unsigned long epic_harx2;
+ unsigned long epic_pmlt;
+ unsigned long epic_tag0;
+ unsigned long epic_tag1;
+ unsigned long epic_tag2;
+ unsigned long epic_tag3;
+ unsigned long epic_tag4;
+ unsigned long epic_tag5;
+ unsigned long epic_tag6;
+ unsigned long epic_tag7;
+ unsigned long epic_data0;
+ unsigned long epic_data1;
+ unsigned long epic_data2;
+ unsigned long epic_data3;
+ unsigned long epic_data4;
+ unsigned long epic_data5;
+ unsigned long epic_data6;
+ unsigned long epic_data7;
+};
+
+struct el_apecs_procdata
+{
+ unsigned long paltemp[32]; /* PAL TEMP REGS. */
+ /* EV4-specific fields */
+ unsigned long exc_addr; /* Address of excepting instruction. */
+ unsigned long exc_sum; /* Summary of arithmetic traps. */
+ unsigned long exc_mask; /* Exception mask (from exc_sum). */
+ unsigned long iccsr; /* IBox hardware enables. */
+ unsigned long pal_base; /* Base address for PALcode. */
+ unsigned long hier; /* Hardware Interrupt Enable. */
+ unsigned long hirr; /* Hardware Interrupt Request. */
+ unsigned long csr; /* D-stream fault info. */
+ unsigned long dc_stat; /* D-cache status (ECC/Parity Err). */
+ unsigned long dc_addr; /* EV3 Phys Addr for ECC/DPERR. */
+ unsigned long abox_ctl; /* ABox Control Register. */
+ unsigned long biu_stat; /* BIU Status. */
+ unsigned long biu_addr; /* BUI Address. */
+ unsigned long biu_ctl; /* BIU Control. */
+ unsigned long fill_syndrome;/* For correcting ECC errors. */
+ unsigned long fill_addr; /* Cache block which was being read */
+ unsigned long va; /* Effective VA of fault or miss. */
+ unsigned long bc_tag; /* Backup Cache Tag Probe Results.*/
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+/*
+ * NOTE: we fudge the window 1 maximum as 48Mb instead of 64Mb, to prevent
+ * virt_to_bus() from returning an address in the first window, for a
+ * data area that goes beyond the 64Mb first DMA window. Sigh...
+ * This MUST match with <asm/dma.h> MAX_DMA_ADDRESS for consistency, but
+ * we can't just use that here, because of header file looping... :-(
+ */
+
+__EXTERN_INLINE unsigned long apecs_virt_to_bus(void * address)
+{
+ unsigned long paddr = virt_to_phys(address);
+ return paddr + APECS_DMA_WIN_BASE;
+}
+
+static inline unsigned long apecs_xl_virt_to_bus(void * address)
+{
+ unsigned long paddr = virt_to_phys(address);
+ if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID)
+ return paddr + APECS_XL_DMA_WIN1_BASE;
+ else
+ return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */
+}
+
+__EXTERN_INLINE void * apecs_bus_to_virt(unsigned long address)
+{
+ /*
+ * This check is a sanity check but also ensures that bus
+ * address 0 maps to virtual address 0 which is useful to
+ * detect null "pointers" (the NCR driver is much simpler if
+ * NULL pointers are preserved).
+ */
+ if (address < APECS_DMA_WIN_BASE)
+ return 0;
+ return phys_to_virt(address - APECS_DMA_WIN_BASE);
+}
+
+static inline void * apecs_xl_bus_to_virt(unsigned long address)
+{
+ /*
+ * This check is a sanity check but also ensures that bus
+ * address 0 maps to virtual address 0 which is useful to
+ * detect null "pointers" (the NCR driver is much simpler if
+ * NULL pointers are preserved).
+ */
+ if (address < APECS_XL_DMA_WIN1_BASE)
+ return 0;
+ else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
+ address -= APECS_XL_DMA_WIN1_BASE;
+ else /* should be more checking here, maybe? */
+ address -= APECS_XL_DMA_WIN2_BASE;
+ return phys_to_virt(address);
+}
+
+/*
+ * I/O functions:
+ *
+ * Unlike Jensen, the APECS machines have no concept of local
+ * I/O---everything goes over the PCI bus.
+ *
+ * There is plenty room for optimization here. In particular,
+ * the Alpha's insb/insw/extb/extw should be useful in moving
+ * data to/from the right byte-lanes.
+ */
+
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+__EXTERN_INLINE unsigned int apecs_inb(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + APECS_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void apecs_outb(unsigned char b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int apecs_inw(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + APECS_IO + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void apecs_outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int apecs_inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + APECS_IO + 0x18);
+}
+
+__EXTERN_INLINE void apecs_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
+ mb();
+}
+
+
+/*
+ * Memory functions. 64-bit and 32-bit accesses are done through
+ * dense memory space, everything else through sparse space.
+ */
+
+__EXTERN_INLINE unsigned long apecs_readb(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long apecs_readw(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long apecs_readl(unsigned long addr)
+{
+ return *(vuip) (addr + APECS_DENSE_MEM);
+}
+
+__EXTERN_INLINE unsigned long apecs_readq(unsigned long addr)
+{
+ return *(vulp) (addr + APECS_DENSE_MEM);
+}
+
+__EXTERN_INLINE void apecs_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
+}
+
+__EXTERN_INLINE void apecs_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
+}
+
+__EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip) (addr + APECS_DENSE_MEM) = b;
+}
+
+__EXTERN_INLINE void apecs_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp) (addr + APECS_DENSE_MEM) = b;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long apecs_dense_mem(unsigned long addr)
+{
+ return APECS_DENSE_MEM;
+}
+
+#undef vip
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#ifdef CONFIG_ALPHA_XL
+#define virt_to_bus apecs_xl_virt_to_bus
+#define bus_to_virt apecs_xl_bus_to_virt
+#else
+#define virt_to_bus apecs_virt_to_bus
+#define bus_to_virt apecs_bus_to_virt
+#endif
+
+#define __inb apecs_inb
+#define __inw apecs_inw
+#define __inl apecs_inl
+#define __outb apecs_outb
+#define __outw apecs_outw
+#define __outl apecs_outl
+#define __readb apecs_readb
+#define __readw apecs_readw
+#define __readl apecs_readl
+#define __readq apecs_readq
+#define __writeb apecs_writeb
+#define __writew apecs_writew
+#define __writel apecs_writel
+#define __writeq apecs_writeq
+#define dense_mem apecs_dense_mem
+
+#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 readq(a) __readq((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_APECS__H__ */
--- /dev/null
+#ifndef __ALPHA_CIA__H__
+#define __ALPHA_CIA__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+/*
+ * CIA 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 **
+** **
+**------------------------------------------------------------------------*/
+
+
+/* CIA 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 CIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
+#define CIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
+#define CIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
+
+#define CIA_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define CIA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define CIA_DMA_WIN_BASE alpha_mv.dma_win_base
+#define CIA_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define CIA_DMA_WIN_BASE CIA_DMA_WIN_SIZE_DEFAULT
+#define CIA_DMA_WIN_SIZE CIA_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/*
+ * 21171-CA Control and Status Registers (p4-1)
+ */
+#define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL)
+#define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
+#define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL)
+#define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL)
+#define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
+#define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL)
+#define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL)
+#define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL)
+
+/*
+ * 21171-CA Diagnostic Registers (p4-2)
+ */
+#define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL)
+#define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
+
+/*
+ * 21171-CA Performance Monitor registers (p4-3)
+ */
+#define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
+#define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
+
+/*
+ * 21171-CA Error registers (p4-3)
+ */
+#define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL)
+#define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL)
+#define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL)
+#define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL)
+#define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
+#define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL)
+#define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL)
+#define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL)
+#define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
+#define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
+#define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL)
+
+/*
+ * 2117A-CA PCI Address Translation Registers.
+ */
+#define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL)
+
+#define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL)
+#define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL)
+#define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL)
+
+#define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL)
+#define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL)
+#define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL)
+
+#define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL)
+#define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL)
+#define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL)
+
+#define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL)
+#define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL)
+#define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL)
+
+/*
+ * 21171-CA System configuration registers (p4-3)
+ */
+#define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL)
+#define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL)
+#define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL)
+#define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL)
+#define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL)
+#define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL)
+#define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL)
+#define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL)
+#define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL)
+#define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL)
+#define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL)
+#define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL)
+
+/*
+ * Memory spaces:
+ */
+#define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL)
+#define CIA_CONF (IDENT_ADDR + 0x8700000000UL)
+#define CIA_IO (IDENT_ADDR + 0x8580000000UL)
+#define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
+#define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL)
+#define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL)
+#define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
+
+/*
+ * ALCOR's GRU ASIC registers
+ */
+#define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL)
+#define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL)
+#define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL)
+#define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL)
+#define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL)
+
+#define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL)
+#define GRU_SCR (IDENT_ADDR + 0x8780000300UL)
+#define GRU_LED (IDENT_ADDR + 0x8780000800UL)
+#define GRU_RESET (IDENT_ADDR + 0x8780000900UL)
+
+#define ALCOR_GRU_INT_REQ_BITS 0x800fffffUL
+#define XLT_GRU_INT_REQ_BITS 0x80003fffUL
+#define GRU_INT_REQ_BITS (alpha_mv.sys.cia.gru_int_req_bits+0)
+
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define CIA_IOC_STAT0_CMD 0xf
+#define CIA_IOC_STAT0_ERR (1<<4)
+#define CIA_IOC_STAT0_LOST (1<<5)
+#define CIA_IOC_STAT0_THIT (1<<6)
+#define CIA_IOC_STAT0_TREF (1<<7)
+#define CIA_IOC_STAT0_CODE_SHIFT 8
+#define CIA_IOC_STAT0_CODE_MASK 0x7
+#define CIA_IOC_STAT0_P_NBR_SHIFT 13
+#define CIA_IOC_STAT0_P_NBR_MASK 0x7ffff
+
+#define CIA_HAE_ADDRESS CIA_IOC_HAE_MEM
+
+/*
+ * Data structure for handling CIA machine checks.
+ */
+
+/* EV5-specific info. */
+struct el_CIA_procdata {
+ unsigned long shadow[8]; /* PALmode shadow registers */
+ unsigned long paltemp[24]; /* PAL temporary registers */
+ /* EV5-specific fields */
+ unsigned long exc_addr; /* Address of excepting instruction. */
+ unsigned long exc_sum; /* Summary of arithmetic traps. */
+ unsigned long exc_mask; /* Exception mask (from exc_sum). */
+ unsigned long exc_base; /* PALbase at time of exception. */
+ unsigned long isr; /* Interrupt summary register. */
+ unsigned long icsr; /* Ibox control register. */
+ unsigned long ic_perr_stat;
+ unsigned long dc_perr_stat;
+ unsigned long va; /* Effective VA of fault or miss. */
+ unsigned long mm_stat;
+ unsigned long sc_addr;
+ unsigned long sc_stat;
+ unsigned long bc_tag_addr;
+ unsigned long ei_addr;
+ unsigned long fill_syn;
+ unsigned long ei_stat;
+ unsigned long ld_lock;
+};
+
+/* System-specific info. */
+struct el_CIA_sysdata_mcheck {
+ unsigned long coma_gcr;
+ unsigned long coma_edsr;
+ unsigned long coma_ter;
+ unsigned long coma_elar;
+ unsigned long coma_ehar;
+ unsigned long coma_ldlr;
+ unsigned long coma_ldhr;
+ unsigned long coma_base0;
+ unsigned long coma_base1;
+ unsigned long coma_base2;
+ unsigned long coma_cnfg0;
+ unsigned long coma_cnfg1;
+ unsigned long coma_cnfg2;
+ unsigned long epic_dcsr;
+ unsigned long epic_pear;
+ unsigned long epic_sear;
+ unsigned long epic_tbr1;
+ unsigned long epic_tbr2;
+ unsigned long epic_pbr1;
+ unsigned long epic_pbr2;
+ unsigned long epic_pmr1;
+ unsigned long epic_pmr2;
+ unsigned long epic_harx1;
+ unsigned long epic_harx2;
+ unsigned long epic_pmlt;
+ unsigned long epic_tag0;
+ unsigned long epic_tag1;
+ unsigned long epic_tag2;
+ unsigned long epic_tag3;
+ unsigned long epic_tag4;
+ unsigned long epic_tag5;
+ unsigned long epic_tag6;
+ unsigned long epic_tag7;
+ unsigned long epic_data0;
+ unsigned long epic_data1;
+ unsigned long epic_data2;
+ unsigned long epic_data3;
+ unsigned long epic_data4;
+ unsigned long epic_data5;
+ unsigned long epic_data6;
+ unsigned long epic_data7;
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+__EXTERN_INLINE unsigned long cia_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + CIA_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * cia_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - CIA_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * CIA (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 vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+__EXTERN_INLINE unsigned int cia_inb(unsigned long addr)
+{
+ long result;
+ result = *(vip) ((addr << 5) + CIA_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void cia_outb(unsigned char b, unsigned long addr)
+{
+ unsigned int w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
+ wmb();
+}
+
+__EXTERN_INLINE unsigned int cia_inw(unsigned long addr)
+{
+ long result;
+ result = *(vip) ((addr << 5) + CIA_IO + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void cia_outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
+ wmb();
+}
+
+__EXTERN_INLINE unsigned int cia_inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + CIA_IO + 0x18);
+}
+
+__EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
+ wmb();
+}
+
+
+/*
+ * 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 cia_srm_base(unsigned long addr)
+{
+ unsigned long mask, base;
+
+ if (addr >= alpha_mv.sm_base_r1
+ && addr <= alpha_mv.sm_base_r1 + CIA_MEM_R1_MASK) {
+ mask = CIA_MEM_R1_MASK;
+ base = CIA_SPARSE_MEM;
+ }
+ else if (addr >= alpha_mv.sm_base_r2
+ && addr <= alpha_mv.sm_base_r2 + CIA_MEM_R2_MASK) {
+ mask = CIA_MEM_R2_MASK;
+ base = CIA_SPARSE_MEM_R2;
+ }
+ else if (addr >= alpha_mv.sm_base_r3
+ && addr <= alpha_mv.sm_base_r3 + CIA_MEM_R3_MASK) {
+ mask = CIA_MEM_R3_MASK;
+ base = CIA_SPARSE_MEM_R3;
+ }
+ else
+ {
+#if 0
+ printk("cia: address 0x%lx not covered by HAE\n", addr);
+#endif
+ return 0;
+ }
+
+ return ((addr & mask) << 5) + base;
+}
+
+__EXTERN_INLINE unsigned long cia_srm_readb(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = cia_srm_base(addr)) == 0)
+ return 0xff;
+ work += 0x00; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long cia_srm_readw(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = cia_srm_base(addr)) == 0)
+ return 0xffff;
+ work += 0x08; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void cia_srm_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long work = cia_srm_base(addr), w;
+ if (work) {
+ work += 0x00; /* add transfer length */
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) work = w;
+ }
+}
+
+__EXTERN_INLINE void cia_srm_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long work = cia_srm_base(addr), w;
+ if (work) {
+ work += 0x08; /* add transfer length */
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) work = w;
+ }
+}
+
+__EXTERN_INLINE unsigned long cia_readb(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ msb = addr & 0xE0000000;
+ addr &= CIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long cia_readw(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ msb = addr & 0xE0000000;
+ addr &= CIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb, w;
+
+ msb = addr & 0xE0000000;
+ addr &= CIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
+}
+
+__EXTERN_INLINE void cia_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb, w;
+
+ msb = addr & 0xE0000000;
+ addr &= CIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
+}
+
+__EXTERN_INLINE unsigned long cia_readl(unsigned long addr)
+{
+ return *(vuip) (addr + CIA_DENSE_MEM);
+}
+
+__EXTERN_INLINE unsigned long cia_readq(unsigned long addr)
+{
+ return *(vulp) (addr + CIA_DENSE_MEM);
+}
+
+__EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip) (addr + CIA_DENSE_MEM) = b;
+}
+
+__EXTERN_INLINE void cia_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp) (addr + CIA_DENSE_MEM) = b;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long cia_dense_mem(unsigned long addr)
+{
+ return CIA_DENSE_MEM;
+}
+
+#undef vip
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus cia_virt_to_bus
+#define bus_to_virt cia_bus_to_virt
+#define __inb cia_inb
+#define __inw cia_inw
+#define __inl cia_inl
+#define __outb cia_outb
+#define __outw cia_outw
+#define __outl cia_outl
+
+#ifdef CONFIG_ALPHA_SRM_SETUP
+#define __readb cia_srm_readb
+#define __readw cia_srm_readw
+#define __writeb cia_srm_writeb
+#define __writew cia_srm_writew
+#else
+#define __readb cia_readb
+#define __readw cia_readw
+#define __writeb cia_writeb
+#define __writew cia_writew
+#endif
+
+#define __readl cia_readl
+#define __readq cia_readq
+#define __writel cia_writel
+#define __writeq cia_writeq
+#define dense_mem cia_dense_mem
+
+#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 inw(port) \
+(__builtin_constant_p((port))?__inw(port):_inw(port))
+#define outw(x, port) \
+(__builtin_constant_p((port))?__outw((x),(port)):_outw((x),(port)))
+
+#define inl(port) __inl(port)
+#define outl(x,port) __outl((x),(port))
+
+#define readl(a) __readl((unsigned long)(a))
+#define readq(a) __readq((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_CIA__H__ */
--- /dev/null
+#ifndef __ALPHA_LCA__H__
+#define __ALPHA_LCA__H__
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/compiler.h>
+
+/*
+ * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
+ * for example).
+ *
+ * This file is based on:
+ *
+ * DECchip 21066 and DECchip 21068 Alpha AXP Microprocessors
+ * Hardware Reference Manual; Digital Equipment Corp.; May 1994;
+ * Maynard, MA; Order Number: EC-N2681-71.
+ */
+
+/*
+ * NOTE: The LCA uses a Host Address Extension (HAE) register to access
+ * PCI addresses that are beyond the first 27 bits of address
+ * space. Updating the HAE requires an external cycle (and
+ * a memory barrier), which tends to be slow. Instead of updating
+ * it on each sparse memory access, we keep the current HAE value
+ * cached in variable cache_hae. Only if the cached HAE differs
+ * from the desired HAE value do we actually updated HAE register.
+ * The HAE register is preserved by the interrupt handler entry/exit
+ * code, so this scheme works even in the presence of interrupts.
+ *
+ * Dense memory space doesn't require the HAE, but is restricted to
+ * aligned 32 and 64 bit accesses. Special Cycle and Interrupt
+ * Acknowledge cycles may also require the use of the HAE. The LCA
+ * limits I/O address space to the bottom 24 bits of address space,
+ * but this easily covers the 16 bit ISA I/O address space.
+ */
+
+/*
+ * NOTE 2! The memory operations do not set any memory barriers, as
+ * it's not needed for cases like a frame buffer that is essentially
+ * memory-like. You need to do them by hand if the operations depend
+ * on ordering.
+ *
+ * Similarly, the port I/O operations do a "mb" only after a write
+ * operation: if an mb is needed before (as in the case of doing
+ * memory mapped I/O first, and then a port I/O operation to the same
+ * device), it needs to be done by hand.
+ *
+ * After the above has bitten me 100 times, I'll give up and just do
+ * the mb all the time, but right now I'm hoping this will work out.
+ * Avoiding mb's may potentially be a noticeable speed improvement,
+ * but I can't honestly say I've tested it.
+ *
+ * Handling interrupts that need to do mb's to synchronize to
+ * non-interrupts is another fun race area. Don't do it (because if
+ * you do, I'll have to do *everything* with interrupts disabled,
+ * ugh).
+ */
+
+#define LCA_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define LCA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define LCA_DMA_WIN_BASE alpha_mv.dma_win_base
+#define LCA_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define LCA_DMA_WIN_BASE LCA_DMA_WIN_BASE_DEFAULT
+#define LCA_DMA_WIN_SIZE LCA_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/*
+ * Memory Controller registers:
+ */
+#define LCA_MEM_BCR0 (IDENT_ADDR + 0x120000000UL)
+#define LCA_MEM_BCR1 (IDENT_ADDR + 0x120000008UL)
+#define LCA_MEM_BCR2 (IDENT_ADDR + 0x120000010UL)
+#define LCA_MEM_BCR3 (IDENT_ADDR + 0x120000018UL)
+#define LCA_MEM_BMR0 (IDENT_ADDR + 0x120000020UL)
+#define LCA_MEM_BMR1 (IDENT_ADDR + 0x120000028UL)
+#define LCA_MEM_BMR2 (IDENT_ADDR + 0x120000030UL)
+#define LCA_MEM_BMR3 (IDENT_ADDR + 0x120000038UL)
+#define LCA_MEM_BTR0 (IDENT_ADDR + 0x120000040UL)
+#define LCA_MEM_BTR1 (IDENT_ADDR + 0x120000048UL)
+#define LCA_MEM_BTR2 (IDENT_ADDR + 0x120000050UL)
+#define LCA_MEM_BTR3 (IDENT_ADDR + 0x120000058UL)
+#define LCA_MEM_GTR (IDENT_ADDR + 0x120000060UL)
+#define LCA_MEM_ESR (IDENT_ADDR + 0x120000068UL)
+#define LCA_MEM_EAR (IDENT_ADDR + 0x120000070UL)
+#define LCA_MEM_CAR (IDENT_ADDR + 0x120000078UL)
+#define LCA_MEM_VGR (IDENT_ADDR + 0x120000080UL)
+#define LCA_MEM_PLM (IDENT_ADDR + 0x120000088UL)
+#define LCA_MEM_FOR (IDENT_ADDR + 0x120000090UL)
+
+/*
+ * I/O Controller registers:
+ */
+#define LCA_IOC_HAE (IDENT_ADDR + 0x180000000UL)
+#define LCA_IOC_CONF (IDENT_ADDR + 0x180000020UL)
+#define LCA_IOC_STAT0 (IDENT_ADDR + 0x180000040UL)
+#define LCA_IOC_STAT1 (IDENT_ADDR + 0x180000060UL)
+#define LCA_IOC_TBIA (IDENT_ADDR + 0x180000080UL)
+#define LCA_IOC_TB_ENA (IDENT_ADDR + 0x1800000a0UL)
+#define LCA_IOC_SFT_RST (IDENT_ADDR + 0x1800000c0UL)
+#define LCA_IOC_PAR_DIS (IDENT_ADDR + 0x1800000e0UL)
+#define LCA_IOC_W_BASE0 (IDENT_ADDR + 0x180000100UL)
+#define LCA_IOC_W_BASE1 (IDENT_ADDR + 0x180000120UL)
+#define LCA_IOC_W_MASK0 (IDENT_ADDR + 0x180000140UL)
+#define LCA_IOC_W_MASK1 (IDENT_ADDR + 0x180000160UL)
+#define LCA_IOC_T_BASE0 (IDENT_ADDR + 0x180000180UL)
+#define LCA_IOC_T_BASE1 (IDENT_ADDR + 0x1800001a0UL)
+#define LCA_IOC_TB_TAG0 (IDENT_ADDR + 0x188000000UL)
+#define LCA_IOC_TB_TAG1 (IDENT_ADDR + 0x188000020UL)
+#define LCA_IOC_TB_TAG2 (IDENT_ADDR + 0x188000040UL)
+#define LCA_IOC_TB_TAG3 (IDENT_ADDR + 0x188000060UL)
+#define LCA_IOC_TB_TAG4 (IDENT_ADDR + 0x188000070UL)
+#define LCA_IOC_TB_TAG5 (IDENT_ADDR + 0x1880000a0UL)
+#define LCA_IOC_TB_TAG6 (IDENT_ADDR + 0x1880000c0UL)
+#define LCA_IOC_TB_TAG7 (IDENT_ADDR + 0x1880000e0UL)
+
+/*
+ * Memory spaces:
+ */
+#define LCA_IACK_SC (IDENT_ADDR + 0x1a0000000UL)
+#define LCA_CONF (IDENT_ADDR + 0x1e0000000UL)
+#define LCA_IO (IDENT_ADDR + 0x1c0000000UL)
+#define LCA_SPARSE_MEM (IDENT_ADDR + 0x200000000UL)
+#define LCA_DENSE_MEM (IDENT_ADDR + 0x300000000UL)
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define LCA_IOC_STAT0_CMD 0xf
+#define LCA_IOC_STAT0_ERR (1<<4)
+#define LCA_IOC_STAT0_LOST (1<<5)
+#define LCA_IOC_STAT0_THIT (1<<6)
+#define LCA_IOC_STAT0_TREF (1<<7)
+#define LCA_IOC_STAT0_CODE_SHIFT 8
+#define LCA_IOC_STAT0_CODE_MASK 0x7
+#define LCA_IOC_STAT0_P_NBR_SHIFT 13
+#define LCA_IOC_STAT0_P_NBR_MASK 0x7ffff
+
+#define LCA_HAE_ADDRESS LCA_IOC_HAE
+
+/* LCA PMR Power Management register defines */
+#define LCA_PMR_ADDR (IDENT_ADDR + 0x120000098UL)
+#define LCA_PMR_PDIV 0x7 /* Primary clock divisor */
+#define LCA_PMR_ODIV 0x38 /* Override clock divisor */
+#define LCA_PMR_INTO 0x40 /* Interrupt override */
+#define LCA_PMR_DMAO 0x80 /* DMA override */
+#define LCA_PMR_OCCEB 0xffff0000L /* Override cycle counter - even bits */
+#define LCA_PMR_OCCOB 0xffff000000000000L /* Override cycle counter - even bits */
+#define LCA_PMR_PRIMARY_MASK 0xfffffffffffffff8
+
+/* LCA PMR Macros */
+
+#define LCA_READ_PMR (*(volatile unsigned long *)LCA_PMR_ADDR)
+#define LCA_WRITE_PMR(d) (*((volatile unsigned long *)LCA_PMR_ADDR) = (d))
+
+#define LCA_GET_PRIMARY(r) ((r) & LCA_PMR_PDIV)
+#define LCA_GET_OVERRIDE(r) (((r) >> 3) & LCA_PMR_PDIV)
+#define LCA_SET_PRIMARY_CLOCK(r, c) ((r) = (((r) & LCA_PMR_PRIMARY_MASK)|(c)))
+
+/* LCA PMR Divisor values */
+#define LCA_PMR_DIV_1 0x0
+#define LCA_PMR_DIV_1_5 0x1
+#define LCA_PMR_DIV_2 0x2
+#define LCA_PMR_DIV_4 0x3
+#define LCA_PMR_DIV_8 0x4
+#define LCA_PMR_DIV_16 0x5
+#define LCA_PMR_DIV_MIN DIV_1
+#define LCA_PMR_DIV_MAX DIV_16
+
+
+/*
+ * Data structure for handling LCA machine checks. Correctable errors
+ * result in a short logout frame, uncorrectable ones in a long one.
+ */
+struct el_lca_mcheck_short {
+ struct el_common h; /* common logout header */
+ unsigned long esr; /* error-status register */
+ unsigned long ear; /* error-address register */
+ unsigned long dc_stat; /* dcache status register */
+ unsigned long ioc_stat0; /* I/O controller status register 0 */
+ unsigned long ioc_stat1; /* I/O controller status register 1 */
+};
+
+struct el_lca_mcheck_long {
+ struct el_common h; /* common logout header */
+ unsigned long pt[31]; /* PAL temps */
+ unsigned long exc_addr; /* exception address */
+ unsigned long pad1[3];
+ unsigned long pal_base; /* PALcode base address */
+ unsigned long hier; /* hw interrupt enable */
+ unsigned long hirr; /* hw interrupt request */
+ unsigned long mm_csr; /* MMU control & status */
+ unsigned long dc_stat; /* data cache status */
+ unsigned long dc_addr; /* data cache addr register */
+ unsigned long abox_ctl; /* address box control register */
+ unsigned long esr; /* error status register */
+ unsigned long ear; /* error address register */
+ unsigned long car; /* cache control register */
+ unsigned long ioc_stat0; /* I/O controller status register 0 */
+ unsigned long ioc_stat1; /* I/O controller status register 1 */
+ unsigned long va; /* virtual address register */
+};
+
+union el_lca {
+ struct el_common * c;
+ struct el_lca_mcheck_long * l;
+ struct el_lca_mcheck_short * s;
+};
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+__EXTERN_INLINE unsigned long lca_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + LCA_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * lca_bus_to_virt(unsigned long address)
+{
+ /*
+ * This check is a sanity check but also ensures that bus
+ * address 0 maps to virtual address 0 which is useful to
+ * detect null "pointers" (the NCR driver is much simpler if
+ * NULL pointers are preserved).
+ */
+ if (address < LCA_DMA_WIN_BASE)
+ return 0;
+ return phys_to_virt(address - LCA_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * Unlike Jensen, the Noname machines have no concept of local
+ * I/O---everything goes over the PCI bus.
+ *
+ * There is plenty room for optimization here. In particular,
+ * the Alpha's insb/insw/extb/extw should be useful in moving
+ * data to/from the right byte-lanes.
+ */
+
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+__EXTERN_INLINE unsigned int lca_inb(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + LCA_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void lca_outb(unsigned char b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + LCA_IO + 0x00) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int lca_inw(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + LCA_IO + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void lca_outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + LCA_IO + 0x08) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int lca_inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + LCA_IO + 0x18);
+}
+
+__EXTERN_INLINE void lca_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + LCA_IO + 0x18) = b;
+ mb();
+}
+
+
+/*
+ * Memory functions. 64-bit and 32-bit accesses are done through
+ * dense memory space, everything else through sparse space.
+ */
+
+__EXTERN_INLINE unsigned long lca_readb(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long lca_readw(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long lca_readl(unsigned long addr)
+{
+ return *(vuip) (addr + LCA_DENSE_MEM);
+}
+
+__EXTERN_INLINE unsigned long lca_readq(unsigned long addr)
+{
+ return *(vulp) (addr + LCA_DENSE_MEM);
+}
+
+__EXTERN_INLINE void lca_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb;
+ unsigned int w;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
+}
+
+__EXTERN_INLINE void lca_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb;
+ unsigned int w;
+
+ if (addr >= (1UL << 24)) {
+ msb = addr & 0xf8000000;
+ addr -= msb;
+ set_hae(msb);
+ }
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
+}
+
+__EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip) (addr + LCA_DENSE_MEM) = b;
+}
+
+__EXTERN_INLINE void lca_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp) (addr + LCA_DENSE_MEM) = b;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long lca_dense_mem(unsigned long addr)
+{
+ return LCA_DENSE_MEM;
+}
+
+#undef vip
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus lca_virt_to_bus
+#define bus_to_virt lca_bus_to_virt
+#define __inb lca_inb
+#define __inw lca_inw
+#define __inl lca_inl
+#define __outb lca_outb
+#define __outw lca_outw
+#define __outl lca_outl
+#define __readb lca_readb
+#define __readw lca_readw
+#define __writeb lca_writeb
+#define __writew lca_writew
+#define __readl lca_readl
+#define __readq lca_readq
+#define __writel lca_writel
+#define __writeq lca_writeq
+#define dense_mem lca_dense_mem
+
+#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 readq(a) __readq((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_LCA__H__ */
--- /dev/null
+#ifndef __ALPHA_MCPCIA__H__
+#define __ALPHA_MCPCIA__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/compiler.h>
+
+/*
+ * MCPCIA is the internal name for a core logic chipset which provides
+ * PCI access for the RAWHIDE family of systems.
+ *
+ * This file is based on:
+ *
+ * RAWHIDE System Programmer's Manual
+ * 16-May-96
+ * Rev. 1.4
+ *
+ */
+
+/*------------------------------------------------------------------------**
+** **
+** 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 **
+** **
+**------------------------------------------------------------------------*/
+
+
+/* MCPCIA 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 MCPCIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
+#define MCPCIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
+#define MCPCIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
+
+#define MCPCIA_DMA_WIN_BASE_DEFAULT (2*1024*1024*1024U)
+#define MCPCIA_DMA_WIN_SIZE_DEFAULT (2*1024*1024*1024U)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define MCPCIA_DMA_WIN_BASE alpha_mv.dma_win_base
+#define MCPCIA_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define MCPCIA_DMA_WIN_BASE MCPCIA_DMA_WIN_BASE_DEFAULT
+#define MCPCIA_DMA_WIN_SIZE MCPCIA_DMA_WIN_SIZE_DEFAULT
+#endif
+
+#define HOSE(h) (((unsigned long)(h)) << 33)
+
+/*
+ * General Registers
+ */
+#define MCPCIA_REV(h) (IDENT_ADDR + 0xf9e0000000UL + HOSE(h))
+#define MCPCIA_WHOAMI(h) (IDENT_ADDR + 0xf9e0000040UL + HOSE(h))
+#define MCPCIA_PCI_LAT(h) (IDENT_ADDR + 0xf9e0000080UL + HOSE(h))
+#define MCPCIA_CAP_CTRL(h) (IDENT_ADDR + 0xf9e0000100UL + HOSE(h))
+#define MCPCIA_HAE_MEM(h) (IDENT_ADDR + 0xf9e0000400UL + HOSE(h))
+#define MCPCIA_HAE_IO(h) (IDENT_ADDR + 0xf9e0000440UL + HOSE(h))
+#if 0
+#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9e0000480UL + HOSE(h))
+#endif
+#define MCPCIA_HAE_DENSE(h) (IDENT_ADDR + 0xf9e00004c0UL + HOSE(h))
+
+/*
+ * Interrupt Control registers
+ */
+#define MCPCIA_INT_CTL(h) (IDENT_ADDR + 0xf9e0000500UL + HOSE(h))
+#define MCPCIA_INT_REQ(h) (IDENT_ADDR + 0xf9e0000540UL + HOSE(h))
+#define MCPCIA_INT_TARG(h) (IDENT_ADDR + 0xf9e0000580UL + HOSE(h))
+#define MCPCIA_INT_ADR(h) (IDENT_ADDR + 0xf9e00005c0UL + HOSE(h))
+#define MCPCIA_INT_ADR_EXT(h) (IDENT_ADDR + 0xf9e0000600UL + HOSE(h))
+#define MCPCIA_INT_MASK0(h) (IDENT_ADDR + 0xf9e0000640UL + HOSE(h))
+#define MCPCIA_INT_MASK1(h) (IDENT_ADDR + 0xf9e0000680UL + HOSE(h))
+#define MCPCIA_INT_ACK0(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
+#define MCPCIA_INT_ACK1(h) (IDENT_ADDR + 0xf9e0003f40UL + HOSE(h))
+
+/*
+ * Performance Monitor registers
+ */
+#define MCPCIA_PERF_MONITOR(h) (IDENT_ADDR + 0xf9e0000300UL + HOSE(h))
+#define MCPCIA_PERF_CONTROL(h) (IDENT_ADDR + 0xf9e0000340UL + HOSE(h))
+
+/*
+ * Diagnostic Registers
+ */
+#define MCPCIA_CAP_DIAG(h) (IDENT_ADDR + 0xf9e0000700UL + HOSE(h))
+#define MCPCIA_TOP_OF_MEM(h) (IDENT_ADDR + 0xf9e00007c0UL + HOSE(h))
+
+/*
+ * Error registers
+ */
+#define MCPCIA_CAP_ERR(h) (IDENT_ADDR + 0xf9e0000880UL + HOSE(h))
+#define MCPCIA_PCI_ERR1(h) (IDENT_ADDR + 0xf9e0001040UL + HOSE(h))
+
+/*
+ * PCI Address Translation Registers.
+ */
+#define MCPCIA_SG_TBIA(h) (IDENT_ADDR + 0xf9e0001300UL + HOSE(h))
+#define MCPCIA_HBASE(h) (IDENT_ADDR + 0xf9e0001340UL + HOSE(h))
+
+#define MCPCIA_W0_BASE(h) (IDENT_ADDR + 0xf9e0001400UL + HOSE(h))
+#define MCPCIA_W0_MASK(h) (IDENT_ADDR + 0xf9e0001440UL + HOSE(h))
+#define MCPCIA_T0_BASE(h) (IDENT_ADDR + 0xf9e0001480UL + HOSE(h))
+
+#define MCPCIA_W1_BASE(h) (IDENT_ADDR + 0xf9e0001500UL + HOSE(h))
+#define MCPCIA_W1_MASK(h) (IDENT_ADDR + 0xf9e0001540UL + HOSE(h))
+#define MCPCIA_T1_BASE(h) (IDENT_ADDR + 0xf9e0001580UL + HOSE(h))
+
+#define MCPCIA_W2_BASE(h) (IDENT_ADDR + 0xf9e0001600UL + HOSE(h))
+#define MCPCIA_W2_MASK(h) (IDENT_ADDR + 0xf9e0001640UL + HOSE(h))
+#define MCPCIA_T2_BASE(h) (IDENT_ADDR + 0xf9e0001680UL + HOSE(h))
+
+#define MCPCIA_W3_BASE(h) (IDENT_ADDR + 0xf9e0001700UL + HOSE(h))
+#define MCPCIA_W3_MASK(h) (IDENT_ADDR + 0xf9e0001740UL + HOSE(h))
+#define MCPCIA_T3_BASE(h) (IDENT_ADDR + 0xf9e0001780UL + HOSE(h))
+
+/*
+ * Memory spaces:
+ */
+#define MCPCIA_CONF(h) (IDENT_ADDR + 0xf9c0000000UL + HOSE(h))
+#define MCPCIA_IO(h) (IDENT_ADDR + 0xf980000000UL + HOSE(h))
+#define MCPCIA_SPARSE(h) (IDENT_ADDR + 0xf800000000UL + HOSE(h))
+#define MCPCIA_DENSE(h) (IDENT_ADDR + 0xf900000000UL + HOSE(h))
+#define _MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
+
+#define MCPCIA_HAE_ADDRESS MCPCIA_HAE_MEM(0)
+#define MCPCIA_IACK_SC _MCPCIA_IACK_SC(0)
+
+/*
+ * Data structure for handling MCPCIA machine checks:
+ */
+struct el_MCPCIA_uncorrected_frame_mcheck {
+ struct el_common header;
+ struct el_common_EV5_uncorrectable_mcheck procdata;
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+__EXTERN_INLINE unsigned long mcpcia_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + MCPCIA_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * mcpcia_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - MCPCIA_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * MCPCIA, the RAWHIDE family PCI/memory support chipset for the EV5 (21164)
+ * and EV56 (21164a) processors, can use either a sparse address mapping
+ * scheme, or the so-called byte-word PCI address space, to get at PCI memory
+ * and I/O.
+ *
+ * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE.
+ */
+
+#define vucp volatile unsigned char *
+#define vusp volatile unsigned short *
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+#if 0 /* BWIO */
+__EXTERN_INLINE unsigned int mcpcia_bw_inb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_IO));
+}
+
+__EXTERN_INLINE void mcpcia_bw_outb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int mcpcia_bw_inw(unsigned long addr)
+{
+ return __kernel_ldwu(*(vusp)(addr+MCPCIA_BW_IO));
+}
+
+__EXTERN_INLINE void mcpcia_bw_outw(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int mcpcia_bw_inl(unsigned long addr)
+{
+ return *(vuip)(addr+MCPCIA_BW_IO);
+}
+
+__EXTERN_INLINE void mcpcia_bw_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+MCPCIA_BW_IO) = b;
+ mb();
+}
+#endif
+
+__EXTERN_INLINE unsigned int mcpcia_inb(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void mcpcia_outb(unsigned char b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned int w;
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int mcpcia_inw(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void mcpcia_outw(unsigned short b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned int w;
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int mcpcia_inl(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ return *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18);
+}
+
+__EXTERN_INLINE void mcpcia_outl(unsigned int b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 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
+ *
+ */
+
+#if 0 /* BWIO */
+__EXTERN_INLINE unsigned long mcpcia_bw_readb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_MEM));
+}
+
+__EXTERN_INLINE unsigned long mcpcia_bw_readw(unsigned long addr)
+{
+ return __kernel_ldbw(*(vusp)(addr+MCPCIA_BW_MEM));
+}
+
+__EXTERN_INLINE unsigned long mcpcia_bw_readl(unsigned long addr)
+{
+ return *(vuip)(addr + MCPCIA_BW_MEM);
+}
+
+__EXTERN_INLINE unsigned long mcpcia_bw_readq(unsigned long addr)
+{
+ return *(vulp)(addr + MCPCIA_BW_MEM);
+}
+
+__EXTERN_INLINE void mcpcia_bw_writeb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_MEM));
+}
+
+__EXTERN_INLINE void mcpcia_bw_writew(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_MEM));
+}
+
+__EXTERN_INLINE void mcpcia_bw_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+MCPCIA_BW_MEM) = b;
+}
+
+__EXTERN_INLINE void mcpcia_bw_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp)(addr+MCPCIA_BW_MEM) = b;
+}
+#endif
+
+__EXTERN_INLINE unsigned long mcpcia_srm_base(unsigned long addr)
+{
+ unsigned long mask, base;
+ unsigned long hose = (addr >> 32) & 3;
+
+ if (addr >= alpha_mv.sm_base_r1
+ && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_R1_MASK) {
+ mask = MCPCIA_MEM_R1_MASK;
+ base = MCPCIA_SPARSE(hose);
+ }
+#if 0
+ /* FIXME FIXME FIXME: SPARSE_MEM_R2 and R3 are not defined? */
+ else if (addr >= alpha_mv.sm_base_r2
+ && addr <= alpha_mv.sm_base_r2 + MCPCIA_MEM_R2_MASK) {
+ mask = MCPCIA_MEM_R2_MASK;
+ base = MCPCIA_SPARSE_MEM_R2;
+ }
+ else if (addr >= alpha_mv.sm_base_r3
+ && addr <= alpha_mv.sm_base_r3 + MCPCIA_MEM_R3_MASK) {
+ mask = MCPCIA_MEM_R3_MASK;
+ base = MCPCIA_SPARSE_MEM_R3;
+ }
+#endif
+ else
+ {
+#if 0
+ printk("mcpcia: address 0x%lx not covered by HAE\n", addr);
+#endif
+ return 0;
+ }
+
+ return ((addr & mask) << 5) + base;
+}
+
+__EXTERN_INLINE unsigned long mcpcia_srm_readb(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = mcpcia_srm_base(addr)) == 0)
+ return 0xff;
+ work += 0x00; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long mcpcia_srm_readw(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = mcpcia_srm_base(addr)) == 0)
+ return 0xffff;
+ work += 0x08; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void mcpcia_srm_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long work = mcpcia_srm_base(addr);
+ if (work) {
+ work += 0x00; /* add transfer length */
+ *(vuip) work = b * 0x01010101;
+ }
+}
+
+__EXTERN_INLINE void mcpcia_srm_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long work = mcpcia_srm_base(addr);
+ if (work) {
+ work += 0x08; /* add transfer length */
+ *(vuip) work = b * 0x00010001;
+ }
+}
+
+__EXTERN_INLINE unsigned long mcpcia_readb(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned long result, msb, work, temp;
+
+ msb = addr & 0xE0000000UL;
+ temp = addr & MCPCIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00);
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long mcpcia_readw(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned long result, msb, work, temp;
+
+ msb = addr & 0xE0000000UL;
+ temp = addr & MCPCIA_MEM_R1_MASK ;
+ set_hae(msb);
+
+ work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08);
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void mcpcia_writeb(unsigned char b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned long msb;
+
+ msb = addr & 0xE0000000;
+ addr &= MCPCIA_MEM_R1_MASK;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101;
+}
+
+__EXTERN_INLINE void mcpcia_writew(unsigned short b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= MCPCIA_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001;
+}
+
+__EXTERN_INLINE unsigned long mcpcia_readl(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ return *(vuip) (addr + MCPCIA_DENSE(hose));
+}
+
+__EXTERN_INLINE unsigned long mcpcia_readq(unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ return *(vulp) (addr + MCPCIA_DENSE(hose));
+}
+
+__EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ *(vuip) (addr + MCPCIA_DENSE(hose)) = b;
+}
+
+__EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long in_addr)
+{
+ unsigned long addr = in_addr & 0xffffffffUL;
+ unsigned long hose = (in_addr >> 32) & 3;
+ *(vulp) (addr + MCPCIA_DENSE(hose)) = b;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long mcpcia_dense_mem(unsigned long addr)
+{
+ return MCPCIA_DENSE((addr >> 32) & 3);
+}
+
+#undef vucp
+#undef vusp
+#undef vip
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus mcpcia_virt_to_bus
+#define bus_to_virt mcpcia_bus_to_virt
+
+#if 0 /* BWIO */
+# define __inb mcpcia_bw_inb
+# define __inw mcpcia_bw_inw
+# define __inl mcpcia_bw_inl
+# define __outb mcpcia_bw_outb
+# define __outw mcpcia_bw_outw
+# define __outl mcpcia_bw_outl
+# define __readb mcpcia_bw_readb
+# define __readw mcpcia_bw_readw
+# define __writeb mcpcia_bw_writeb
+# define __writew mcpcia_bw_writew
+# define __readl mcpcia_bw_readl
+# define __readq mcpcia_bw_readq
+# define __writel mcpcia_bw_writel
+# define __writeq mcpcia_bw_writeq
+#else
+# define __inb mcpcia_inb
+# define __inw mcpcia_inw
+# define __inl mcpcia_inl
+# define __outb mcpcia_outb
+# define __outw mcpcia_outw
+# define __outl mcpcia_outl
+# ifdef CONFIG_ALPHA_SRM_SETUP
+# define __readb mcpcia_srm_readb
+# define __readw mcpcia_srm_readw
+# define __writeb mcpcia_srm_writeb
+# define __writew mcpcia_srm_writew
+# else
+# define __readb mcpcia_readb
+# define __readw mcpcia_readw
+# define __writeb mcpcia_writeb
+# define __writew mcpcia_writew
+# endif
+# define __readl mcpcia_readl
+# define __readq mcpcia_readq
+# define __writel mcpcia_writel
+# define __writeq mcpcia_writeq
+#endif /* BWIO */
+
+#define dense_mem mcpcia_dense_mem
+
+#if 0 /* BWIO */
+# define inb(port) __inb((port))
+# define inw(port) __inw((port))
+# define inl(port) __inl((port))
+# define outb(x, port) __outb((x),(port))
+# define outw(x, port) __outw((x),(port))
+# define outl(x, port) __outl((x),(port))
+# define readb(addr) __readb((addr))
+# define readw(addr) __readw((addr))
+# define writeb(b, addr) __writeb((b),(addr))
+# define writew(b, addr) __writew((b),(addr))
+#else
+# 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)))
+#endif /* BWIO */
+
+#define readl(a) __readl((unsigned long)(a))
+#define readq(a) __readq((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_MCPCIA__H__ */
--- /dev/null
+#ifndef __ALPHA_PYXIS__H__
+#define __ALPHA_PYXIS__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+/*
+ * PYXIS is the internal name for a core logic chipset which provides
+ * memory controller and PCI access for the 21164A chip based systems.
+ *
+ * This file is based on:
+ *
+ * Pyxis Chipset Spec
+ * 14-Jun-96
+ * Rev. X2.0
+ *
+ */
+
+/*------------------------------------------------------------------------**
+** **
+** 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 **
+** **
+**------------------------------------------------------------------------*/
+
+
+/* CIA 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 PYXIS_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
+#define PYXIS_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
+#define PYXIS_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
+
+#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define PYXIS_DMA_WIN_BASE alpha_mv.dma_win_base
+#define PYXIS_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define PYXIS_DMA_WIN_BASE PYXIS_DMA_WIN_BASE_DEFAULT
+#define PYXIS_DMA_WIN_SIZE PYXIS_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/*
+ * General Registers
+ */
+#define PYXIS_REV (IDENT_ADDR + 0x8740000080UL)
+#define PYXIS_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
+#define PYXIS_CTRL (IDENT_ADDR + 0x8740000100UL)
+#define PYXIS_CTRL1 (IDENT_ADDR + 0x8740000140UL)
+#define PYXIS_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL)
+
+#define PYXIS_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
+#define PYXIS_HAE_IO (IDENT_ADDR + 0x8740000440UL)
+#define PYXIS_CFG (IDENT_ADDR + 0x8740000480UL)
+
+/*
+ * Diagnostic Registers
+ */
+#define PYXIS_DIAG (IDENT_ADDR + 0x8740002000UL)
+#define PYXIS_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
+
+/*
+ * Performance Monitor registers
+ */
+#define PYXIS_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
+#define PYXIS_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
+
+/*
+ * Error registers
+ */
+#define PYXIS_ERR (IDENT_ADDR + 0x8740008200UL)
+#define PYXIS_STAT (IDENT_ADDR + 0x8740008240UL)
+#define PYXIS_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
+#define PYXIS_SYN (IDENT_ADDR + 0x8740008300UL)
+#define PYXIS_ERR_DATA (IDENT_ADDR + 0x8740008308UL)
+
+#define PYXIS_MEAR (IDENT_ADDR + 0x8740008400UL)
+#define PYXIS_MESR (IDENT_ADDR + 0x8740008440UL)
+#define PYXIS_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
+#define PYXIS_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
+#define PYXIS_PCI_ERR2 (IDENT_ADDR + 0x8740008880UL)
+
+/*
+ * PCI Address Translation Registers.
+ */
+#define PYXIS_TBIA (IDENT_ADDR + 0x8760000100UL)
+
+#define PYXIS_W0_BASE (IDENT_ADDR + 0x8760000400UL)
+#define PYXIS_W0_MASK (IDENT_ADDR + 0x8760000440UL)
+#define PYXIS_T0_BASE (IDENT_ADDR + 0x8760000480UL)
+
+#define PYXIS_W1_BASE (IDENT_ADDR + 0x8760000500UL)
+#define PYXIS_W1_MASK (IDENT_ADDR + 0x8760000540UL)
+#define PYXIS_T1_BASE (IDENT_ADDR + 0x8760000580UL)
+
+#define PYXIS_W2_BASE (IDENT_ADDR + 0x8760000600UL)
+#define PYXIS_W2_MASK (IDENT_ADDR + 0x8760000640UL)
+#define PYXIS_T2_BASE (IDENT_ADDR + 0x8760000680UL)
+
+#define PYXIS_W3_BASE (IDENT_ADDR + 0x8760000700UL)
+#define PYXIS_W3_MASK (IDENT_ADDR + 0x8760000740UL)
+#define PYXIS_T3_BASE (IDENT_ADDR + 0x8760000780UL)
+
+/*
+ * Memory Control registers
+ */
+#define PYXIS_MCR (IDENT_ADDR + 0x8750000000UL)
+
+/*
+ * Memory spaces:
+ */
+#define PYXIS_IACK_SC (IDENT_ADDR + 0x8720000000UL)
+#define PYXIS_CONF (IDENT_ADDR + 0x8700000000UL)
+#define PYXIS_IO (IDENT_ADDR + 0x8580000000UL)
+#define PYXIS_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
+#define PYXIS_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL)
+#define PYXIS_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL)
+#define PYXIS_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
+
+/*
+ * Byte/Word PCI Memory Spaces:
+ */
+#define PYXIS_BW_MEM (IDENT_ADDR + 0x8800000000UL)
+#define PYXIS_BW_IO (IDENT_ADDR + 0x8900000000UL)
+#define PYXIS_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL)
+#define PYXIS_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL)
+
+/*
+ * Interrupt Control registers
+ */
+#define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL)
+#define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL)
+#define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL)
+#define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL)
+#define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL)
+#define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL)
+#define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL)
+#define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL)
+#define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL)
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define PYXIS_STAT0_CMD 0xf
+#define PYXIS_STAT0_ERR (1<<4)
+#define PYXIS_STAT0_LOST (1<<5)
+#define PYXIS_STAT0_THIT (1<<6)
+#define PYXIS_STAT0_TREF (1<<7)
+#define PYXIS_STAT0_CODE_SHIFT 8
+#define PYXIS_STAT0_CODE_MASK 0x7
+#define PYXIS_STAT0_P_NBR_SHIFT 13
+#define PYXIS_STAT0_P_NBR_MASK 0x7ffff
+
+#define PYXIS_HAE_ADDRESS PYXIS_HAE_MEM
+
+/*
+ * Data structure for handling PYXIS machine checks:
+ */
+struct el_PYXIS_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;
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+/* Ruffian doesn't do 1G PCI window */
+
+static inline unsigned long pyxis_ruffian_virt_to_bus(void * address)
+{
+ return virt_to_phys(address);
+}
+
+static inline void * pyxis_ruffian_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address);
+}
+
+__EXTERN_INLINE unsigned long pyxis_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + PYXIS_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * pyxis_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - PYXIS_DMA_WIN_BASE);
+}
+
+
+/*
+ * I/O functions:
+ *
+ * PYXIS, the 21174 PCI/memory support chipset for the EV56 (21164A)
+ * and PCA56 (21164PC) processors, can use either a sparse address
+ * mapping scheme, or the so-called byte-word PCI address space, to
+ * get at PCI memory and I/O.
+ */
+
+#define vucp volatile unsigned char *
+#define vusp volatile unsigned short *
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+__EXTERN_INLINE unsigned int pyxis_bw_inb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_IO));
+}
+
+__EXTERN_INLINE void pyxis_bw_outb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr+PYXIS_BW_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int pyxis_bw_inw(unsigned long addr)
+{
+ return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_IO));
+}
+
+__EXTERN_INLINE void pyxis_bw_outw(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+PYXIS_BW_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int pyxis_bw_inl(unsigned long addr)
+{
+ return *(vuip)(addr+PYXIS_BW_IO);
+}
+
+__EXTERN_INLINE void pyxis_bw_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+PYXIS_BW_IO) = b;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int pyxis_inb(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + PYXIS_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void pyxis_outb(unsigned char b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + PYXIS_IO + 0x00) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int pyxis_inw(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + PYXIS_IO + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void pyxis_outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + PYXIS_IO + 0x08) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int pyxis_inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + PYXIS_IO + 0x18);
+}
+
+__EXTERN_INLINE void pyxis_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + PYXIS_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 pyxis_bw_readb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_MEM));
+}
+
+__EXTERN_INLINE unsigned long pyxis_bw_readw(unsigned long addr)
+{
+ return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_MEM));
+}
+
+__EXTERN_INLINE unsigned long pyxis_bw_readl(unsigned long addr)
+{
+ return *(vuip)(addr+PYXIS_BW_MEM);
+}
+
+__EXTERN_INLINE unsigned long pyxis_bw_readq(unsigned long addr)
+{
+ return *(vulp)(addr+PYXIS_BW_MEM);
+}
+
+__EXTERN_INLINE void pyxis_bw_writeb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr+PYXIS_BW_MEM));
+ mb();
+}
+
+__EXTERN_INLINE void pyxis_bw_writew(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+PYXIS_BW_MEM));
+ mb();
+}
+
+__EXTERN_INLINE void pyxis_bw_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+PYXIS_BW_MEM) = b;
+}
+
+__EXTERN_INLINE void pyxis_bw_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp)(addr+PYXIS_BW_MEM) = b;
+}
+
+__EXTERN_INLINE unsigned long pyxis_srm_base(unsigned long addr)
+{
+ unsigned long mask, base;
+
+ if (addr >= alpha_mv.sm_base_r1
+ && addr <= alpha_mv.sm_base_r1 + PYXIS_MEM_R1_MASK) {
+ mask = PYXIS_MEM_R1_MASK;
+ base = PYXIS_SPARSE_MEM;
+ }
+ else if (addr >= alpha_mv.sm_base_r2
+ && addr <= alpha_mv.sm_base_r2 + PYXIS_MEM_R2_MASK) {
+ mask = PYXIS_MEM_R2_MASK;
+ base = PYXIS_SPARSE_MEM_R2;
+ }
+ else if (addr >= alpha_mv.sm_base_r3
+ && addr <= alpha_mv.sm_base_r3 + PYXIS_MEM_R3_MASK) {
+ mask = PYXIS_MEM_R3_MASK;
+ base = PYXIS_SPARSE_MEM_R3;
+ }
+ else
+ {
+#if 0
+ printk("pyxis: address 0x%lx not covered by HAE\n", addr);
+#endif
+ return 0;
+ }
+
+ return ((addr & mask) << 5) + base;
+}
+
+__EXTERN_INLINE unsigned long pyxis_srm_readb(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = pyxis_srm_base(addr)) == 0)
+ return 0xff;
+ work += 0x00; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long pyxis_srm_readw(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = pyxis_srm_base(addr)) == 0)
+ return 0xffff;
+ work += 0x08; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void pyxis_srm_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long work = pyxis_srm_base(addr);
+ if (work) {
+ work += 0x00; /* add transfer length */
+ *(vuip) work = b * 0x01010101;
+ }
+}
+
+__EXTERN_INLINE void pyxis_srm_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long work = pyxis_srm_base(addr);
+ if (work) {
+ work += 0x08; /* add transfer length */
+ *(vuip) work = b * 0x00010001;
+ }
+}
+
+__EXTERN_INLINE unsigned long pyxis_readb(unsigned long addr)
+{
+ unsigned long result, msb, work, temp;
+
+ msb = addr & 0xE0000000UL;
+ temp = addr & PYXIS_MEM_R1_MASK ;
+ set_hae(msb);
+
+ work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00);
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long pyxis_readw(unsigned long addr)
+{
+ unsigned long result, msb, work, temp;
+
+ msb = addr & 0xE0000000UL;
+ temp = addr & PYXIS_MEM_R1_MASK ;
+ set_hae(msb);
+
+ work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08);
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void pyxis_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= PYXIS_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101;
+}
+
+__EXTERN_INLINE void pyxis_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= PYXIS_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001;
+}
+
+__EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr)
+{
+ return *(vuip) (addr + PYXIS_DENSE_MEM);
+}
+
+__EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr)
+{
+ return *(vulp) (addr + PYXIS_DENSE_MEM);
+}
+
+__EXTERN_INLINE void pyxis_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip) (addr + PYXIS_DENSE_MEM) = b;
+}
+
+__EXTERN_INLINE void pyxis_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp) (addr + PYXIS_DENSE_MEM) = b;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long pyxis_dense_mem(unsigned long addr)
+{
+ return PYXIS_DENSE_MEM;
+}
+
+#undef vucp
+#undef vusp
+#undef vip
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#ifdef CONFIG_ALPHA_RUFFIAN
+#define virt_to_bus pyxis_ruffian_virt_to_bus
+#define bus_to_virt pyxis_ruffian_bus_to_virt
+#else
+#define virt_to_bus pyxis_virt_to_bus
+#define bus_to_virt pyxis_bus_to_virt
+#endif
+
+#ifdef BWIO_ENABLED
+# define __inb pyxis_bw_inb
+# define __inw pyxis_bw_inw
+# define __inl pyxis_bw_inl
+# define __outb pyxis_bw_outb
+# define __outw pyxis_bw_outw
+# define __outl pyxis_bw_outl
+# define __readb pyxis_bw_readb
+# define __readw pyxis_bw_readw
+# define __writeb pyxis_bw_writeb
+# define __writew pyxis_bw_writew
+# define __readl pyxis_bw_readl
+# define __readq pyxis_bw_readq
+# define __writel pyxis_bw_writel
+# define __writeq pyxis_bw_writeq
+#else
+# define __inb pyxis_inb
+# define __inw pyxis_inw
+# define __inl pyxis_inl
+# define __outb pyxis_outb
+# define __outw pyxis_outw
+# define __outl pyxis_outl
+# ifdef CONFIG_ALPHA_SRM_SETUP
+# define __readb pyxis_srm_readb
+# define __readw pyxis_srm_readw
+# define __writeb pyxis_srm_writeb
+# define __writew pyxis_srm_writew
+# else
+# define __readb pyxis_readb
+# define __readw pyxis_readw
+# define __writeb pyxis_writeb
+# define __writew pyxis_writew
+# endif
+# define __readl pyxis_readl
+# define __readq pyxis_readq
+# define __writel pyxis_writel
+# define __writeq pyxis_writeq
+#endif /* BWIO */
+
+#define dense_mem pyxis_dense_mem
+
+#ifdef BWIO_ENABLED
+# define inb(port) __inb((port))
+# define inw(port) __inw((port))
+# define inl(port) __inl((port))
+# define outb(x, port) __outb((x),(port))
+# define outw(x, port) __outw((x),(port))
+# define outl(x, port) __outl((x),(port))
+# define readb(addr) __readb((addr))
+# define readw(addr) __readw((addr))
+# define writeb(b, addr) __writeb((b),(addr))
+# define writew(b, addr) __writew((b),(addr))
+#else
+# 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)))
+#endif /* BWIO */
+
+#define readl(a) __readl((unsigned long)(a))
+#define readq(a) __readq((unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_PYXIS__H__ */
--- /dev/null
+#ifndef __ALPHA_T2__H__
+#define __ALPHA_T2__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+
+/*
+ * T2 is the internal name for the core logic chipset which provides
+ * memory controller and PCI access for the SABLE-based systems.
+ *
+ * This file is based on:
+ *
+ * SABLE I/O Specification
+ * Revision/Update Information: 1.3
+ *
+ * jestabro@amt.tay1.dec.com Initial Version.
+ *
+ */
+
+#define T2_MEM_R1_MASK 0x03ffffff /* Mem sparse region 1 mask is 26 bits */
+
+#define T2_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define T2_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define T2_DMA_WIN_BASE alpha_mv.dma_win_base
+#define T2_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define T2_DMA_WIN_BASE T2_DMA_WIN_BASE_DEFAULT
+#define T2_DMA_WIN_SIZE T2_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/* GAMMA-SABLE is a SABLE with EV5-based CPUs */
+#define _GAMMA_BIAS 0x8000000000UL
+
+#if defined(CONFIG_ALPHA_GENERIC)
+#define GAMMA_BIAS alpha_mv.sys.t2.gamma_bias
+#elif defined(CONFIG_ALPHA_GAMMA)
+#define GAMMA_BIAS _GAMMA_BIAS
+#else
+#define GAMMA_BIAS 0
+#endif
+
+/*
+ * Memory spaces:
+ */
+#define T2_CONF (IDENT_ADDR + GAMMA_BIAS + 0x390000000UL)
+#define T2_IO (IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL)
+#define T2_SPARSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x200000000UL)
+#define T2_DENSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL)
+
+#define T2_IOCSR (IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL)
+#define T2_CERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL)
+#define T2_CERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000040UL)
+#define T2_CERR3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000060UL)
+#define T2_PERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000080UL)
+#define T2_PERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000a0UL)
+#define T2_PSCR (IDENT_ADDR + GAMMA_BIAS + 0x38e0000c0UL)
+#define T2_HAE_1 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000e0UL)
+#define T2_HAE_2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000100UL)
+#define T2_HBASE (IDENT_ADDR + GAMMA_BIAS + 0x38e000120UL)
+#define T2_WBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000140UL)
+#define T2_WMASK1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000160UL)
+#define T2_TBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000180UL)
+#define T2_WBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001a0UL)
+#define T2_WMASK2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001c0UL)
+#define T2_TBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001e0UL)
+#define T2_TLBBR (IDENT_ADDR + GAMMA_BIAS + 0x38e000200UL)
+
+#define T2_HAE_3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000240UL)
+#define T2_HAE_4 (IDENT_ADDR + GAMMA_BIAS + 0x38e000260UL)
+
+#define T2_HAE_ADDRESS T2_HAE_1
+
+/* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to
+ 3.8fff.ffff
+ *
+ * +--------------+ 3 8000 0000
+ * | CPU 0 CSRs |
+ * +--------------+ 3 8100 0000
+ * | CPU 1 CSRs |
+ * +--------------+ 3 8200 0000
+ * | CPU 2 CSRs |
+ * +--------------+ 3 8300 0000
+ * | CPU 3 CSRs |
+ * +--------------+ 3 8400 0000
+ * | CPU Reserved |
+ * +--------------+ 3 8700 0000
+ * | Mem Reserved |
+ * +--------------+ 3 8800 0000
+ * | Mem 0 CSRs |
+ * +--------------+ 3 8900 0000
+ * | Mem 1 CSRs |
+ * +--------------+ 3 8a00 0000
+ * | Mem 2 CSRs |
+ * +--------------+ 3 8b00 0000
+ * | Mem 3 CSRs |
+ * +--------------+ 3 8c00 0000
+ * | Mem Reserved |
+ * +--------------+ 3 8e00 0000
+ * | PCI Bridge |
+ * +--------------+ 3 8f00 0000
+ * | Expansion IO |
+ * +--------------+ 3 9000 0000
+ *
+ *
+ */
+#define T2_CPU0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x380000000L)
+#define T2_CPU1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x381000000L)
+#define T2_CPU2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x382000000L)
+#define T2_CPU3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x383000000L)
+#define T2_MEM0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x388000000L)
+#define T2_MEM1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x389000000L)
+#define T2_MEM2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38a000000L)
+#define T2_MEM3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38b000000L)
+
+
+/*
+ * Sable CPU Module CSRS
+ *
+ * These are CSRs for hardware other than the CPU chip on the CPU module.
+ * The CPU module has Backup Cache control logic, Cbus control logic, and
+ * interrupt control logic on it. There is a duplicate tag store to speed
+ * up maintaining cache coherency.
+ */
+
+struct sable_cpu_csr {
+ unsigned long bcc; long fill_00[3]; /* Backup Cache Control */
+ unsigned long bcce; long fill_01[3]; /* Backup Cache Correctable Error */
+ unsigned long bccea; long fill_02[3]; /* B-Cache Corr Err Address Latch */
+ unsigned long bcue; long fill_03[3]; /* B-Cache Uncorrectable Error */
+ unsigned long bcuea; long fill_04[3]; /* B-Cache Uncorr Err Addr Latch */
+ unsigned long dter; long fill_05[3]; /* Duplicate Tag Error */
+ unsigned long cbctl; long fill_06[3]; /* CBus Control */
+ unsigned long cbe; long fill_07[3]; /* CBus Error */
+ unsigned long cbeal; long fill_08[3]; /* CBus Error Addr Latch low */
+ unsigned long cbeah; long fill_09[3]; /* CBus Error Addr Latch high */
+ unsigned long pmbx; long fill_10[3]; /* Processor Mailbox */
+ unsigned long ipir; long fill_11[3]; /* Inter-Processor Int Request */
+ unsigned long sic; long fill_12[3]; /* System Interrupt Clear */
+ unsigned long adlk; long fill_13[3]; /* Address Lock (LDxL/STxC) */
+ unsigned long madrl; long fill_14[3]; /* CBus Miss Address */
+ unsigned long rev; long fill_15[3]; /* CMIC Revision */
+};
+
+/*
+ * Data structure for handling T2 machine checks:
+ */
+struct el_t2_frame_header {
+ unsigned int elcf_fid; /* Frame ID (from above) */
+ unsigned int elcf_size; /* Size of frame in bytes */
+};
+
+struct el_t2_procdata_mcheck {
+ unsigned long elfmc_paltemp[32]; /* PAL TEMP REGS. */
+ /* EV4-specific fields */
+ unsigned long elfmc_exc_addr; /* Addr of excepting insn. */
+ unsigned long elfmc_exc_sum; /* Summary of arith traps. */
+ unsigned long elfmc_exc_mask; /* Exception mask (from exc_sum). */
+ unsigned long elfmc_iccsr; /* IBox hardware enables. */
+ unsigned long elfmc_pal_base; /* Base address for PALcode. */
+ unsigned long elfmc_hier; /* Hardware Interrupt Enable. */
+ unsigned long elfmc_hirr; /* Hardware Interrupt Request. */
+ unsigned long elfmc_mm_csr; /* D-stream fault info. */
+ unsigned long elfmc_dc_stat; /* D-cache status (ECC/Parity Err). */
+ unsigned long elfmc_dc_addr; /* EV3 Phys Addr for ECC/DPERR. */
+ unsigned long elfmc_abox_ctl; /* ABox Control Register. */
+ unsigned long elfmc_biu_stat; /* BIU Status. */
+ unsigned long elfmc_biu_addr; /* BUI Address. */
+ unsigned long elfmc_biu_ctl; /* BIU Control. */
+ unsigned long elfmc_fill_syndrome; /* For correcting ECC errors. */
+ unsigned long elfmc_fill_addr;/* Cache block which was being read. */
+ unsigned long elfmc_va; /* Effective VA of fault or miss. */
+ unsigned long elfmc_bc_tag; /* Backup Cache Tag Probe Results. */
+};
+
+/*
+ * Sable processor specific Machine Check Data segment.
+ */
+
+struct el_t2_logout_header {
+ unsigned int elfl_size; /* size in bytes of logout area. */
+ int elfl_sbz1:31; /* Should be zero. */
+ char elfl_retry:1; /* Retry flag. */
+ unsigned int elfl_procoffset; /* Processor-specific offset. */
+ unsigned int elfl_sysoffset; /* Offset of system-specific. */
+ unsigned int elfl_error_type; /* PAL error type code. */
+ unsigned int elfl_frame_rev; /* PAL Frame revision. */
+};
+struct el_t2_sysdata_mcheck {
+ unsigned long elcmc_bcc; /* CSR 0 */
+ unsigned long elcmc_bcce; /* CSR 1 */
+ unsigned long elcmc_bccea; /* CSR 2 */
+ unsigned long elcmc_bcue; /* CSR 3 */
+ unsigned long elcmc_bcuea; /* CSR 4 */
+ unsigned long elcmc_dter; /* CSR 5 */
+ unsigned long elcmc_cbctl; /* CSR 6 */
+ unsigned long elcmc_cbe; /* CSR 7 */
+ unsigned long elcmc_cbeal; /* CSR 8 */
+ unsigned long elcmc_cbeah; /* CSR 9 */
+ unsigned long elcmc_pmbx; /* CSR 10 */
+ unsigned long elcmc_ipir; /* CSR 11 */
+ unsigned long elcmc_sic; /* CSR 12 */
+ unsigned long elcmc_adlk; /* CSR 13 */
+ unsigned long elcmc_madrl; /* CSR 14 */
+ unsigned long elcmc_crrev4; /* CSR 15 */
+};
+
+/*
+ * Sable memory error frame - sable pfms section 3.42
+ */
+struct el_t2_data_memory {
+ struct el_t2_frame_header elcm_hdr; /* ID$MEM-FERR = 0x08 */
+ unsigned int elcm_module; /* Module id. */
+ unsigned int elcm_res04; /* Reserved. */
+ unsigned long elcm_merr; /* CSR0: Error Reg 1. */
+ unsigned long elcm_mcmd1; /* CSR1: Command Trap 1. */
+ unsigned long elcm_mcmd2; /* CSR2: Command Trap 2. */
+ unsigned long elcm_mconf; /* CSR3: Configuration. */
+ unsigned long elcm_medc1; /* CSR4: EDC Status 1. */
+ unsigned long elcm_medc2; /* CSR5: EDC Status 2. */
+ unsigned long elcm_medcc; /* CSR6: EDC Control. */
+ unsigned long elcm_msctl; /* CSR7: Stream Buffer Control. */
+ unsigned long elcm_mref; /* CSR8: Refresh Control. */
+ unsigned long elcm_filter; /* CSR9: CRD Filter Control. */
+};
+
+
+/*
+ * Sable other CPU error frame - sable pfms section 3.43
+ */
+struct el_t2_data_other_cpu {
+ short elco_cpuid; /* CPU ID */
+ short elco_res02[3];
+ unsigned long elco_bcc; /* CSR 0 */
+ unsigned long elco_bcce; /* CSR 1 */
+ unsigned long elco_bccea; /* CSR 2 */
+ unsigned long elco_bcue; /* CSR 3 */
+ unsigned long elco_bcuea; /* CSR 4 */
+ unsigned long elco_dter; /* CSR 5 */
+ unsigned long elco_cbctl; /* CSR 6 */
+ unsigned long elco_cbe; /* CSR 7 */
+ unsigned long elco_cbeal; /* CSR 8 */
+ unsigned long elco_cbeah; /* CSR 9 */
+ unsigned long elco_pmbx; /* CSR 10 */
+ unsigned long elco_ipir; /* CSR 11 */
+ unsigned long elco_sic; /* CSR 12 */
+ unsigned long elco_adlk; /* CSR 13 */
+ unsigned long elco_madrl; /* CSR 14 */
+ unsigned long elco_crrev4; /* CSR 15 */
+};
+
+/*
+ * Sable other CPU error frame - sable pfms section 3.44
+ */
+struct el_t2_data_t2{
+ struct el_t2_frame_header elct_hdr; /* ID$T2-FRAME */
+ unsigned long elct_iocsr; /* IO Control and Status Register */
+ unsigned long elct_cerr1; /* Cbus Error Register 1 */
+ unsigned long elct_cerr2; /* Cbus Error Register 2 */
+ unsigned long elct_cerr3; /* Cbus Error Register 3 */
+ unsigned long elct_perr1; /* PCI Error Register 1 */
+ unsigned long elct_perr2; /* PCI Error Register 2 */
+ unsigned long elct_hae0_1; /* High Address Extension Register 1 */
+ unsigned long elct_hae0_2; /* High Address Extension Register 2 */
+ unsigned long elct_hbase; /* High Base Register */
+ unsigned long elct_wbase1; /* Window Base Register 1 */
+ unsigned long elct_wmask1; /* Window Mask Register 1 */
+ unsigned long elct_tbase1; /* Translated Base Register 1 */
+ unsigned long elct_wbase2; /* Window Base Register 2 */
+ unsigned long elct_wmask2; /* Window Mask Register 2 */
+ unsigned long elct_tbase2; /* Translated Base Register 2 */
+ unsigned long elct_tdr0; /* TLB Data Register 0 */
+ unsigned long elct_tdr1; /* TLB Data Register 1 */
+ unsigned long elct_tdr2; /* TLB Data Register 2 */
+ unsigned long elct_tdr3; /* TLB Data Register 3 */
+ unsigned long elct_tdr4; /* TLB Data Register 4 */
+ unsigned long elct_tdr5; /* TLB Data Register 5 */
+ unsigned long elct_tdr6; /* TLB Data Register 6 */
+ unsigned long elct_tdr7; /* TLB Data Register 7 */
+};
+
+/*
+ * Sable error log data structure - sable pfms section 3.40
+ */
+struct el_t2_data_corrected {
+ unsigned long elcpb_biu_stat;
+ unsigned long elcpb_biu_addr;
+ unsigned long elcpb_biu_ctl;
+ unsigned long elcpb_fill_syndrome;
+ unsigned long elcpb_fill_addr;
+ unsigned long elcpb_bc_tag;
+};
+
+/*
+ * Sable error log data structure
+ * Note there are 4 memory slots on sable (see t2.h)
+ */
+struct el_t2_frame_mcheck {
+ struct el_t2_frame_header elfmc_header; /* ID$P-FRAME_MCHECK */
+ struct el_t2_logout_header elfmc_hdr;
+ struct el_t2_procdata_mcheck elfmc_procdata;
+ struct el_t2_sysdata_mcheck elfmc_sysdata;
+ struct el_t2_data_t2 elfmc_t2data;
+ struct el_t2_data_memory elfmc_memdata[4];
+ struct el_t2_frame_header elfmc_footer; /* empty */
+};
+
+
+/*
+ * Sable error log data structures on memory errors
+ */
+struct el_t2_frame_corrected {
+ struct el_t2_frame_header elfcc_header; /* ID$P-BC-COR */
+ struct el_t2_logout_header elfcc_hdr;
+ struct el_t2_data_corrected elfcc_procdata;
+/* struct el_t2_data_t2 elfcc_t2data; */
+/* struct el_t2_data_memory elfcc_memdata[4]; */
+ struct el_t2_frame_header elfcc_footer; /* empty */
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+
+__EXTERN_INLINE unsigned long t2_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + T2_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * t2_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - T2_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * T2 (the core logic PCI/memory support chipset for the SABLE
+ * series of processors uses a sparse address mapping scheme to
+ * get at PCI memory and I/O.
+ */
+
+#define vip volatile int *
+#define vuip volatile unsigned int *
+
+__EXTERN_INLINE unsigned int t2_inb(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + T2_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE void t2_outb(unsigned char b, unsigned long addr)
+{
+ unsigned long w;
+
+ w = __kernel_insbl(b, addr & 3);
+ *(vuip) ((addr << 5) + T2_IO + 0x00) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int t2_inw(unsigned long addr)
+{
+ long result = *(vip) ((addr << 5) + T2_IO + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+__EXTERN_INLINE void t2_outw(unsigned short b, unsigned long addr)
+{
+ unsigned int w;
+
+ w = __kernel_inswl(b, addr & 3);
+ *(vuip) ((addr << 5) + T2_IO + 0x08) = w;
+ mb();
+}
+
+__EXTERN_INLINE unsigned int t2_inl(unsigned long addr)
+{
+ return *(vuip) ((addr << 5) + T2_IO + 0x18);
+}
+
+__EXTERN_INLINE void t2_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip) ((addr << 5) + T2_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 t2_srm_base(unsigned long addr)
+{
+ if ((addr >= alpha_mv.sm_base_r1
+ && addr <= alpha_mv.sm_base_r1 + T2_MEM_R1_MASK)
+ || (addr >= 512*1024 && addr < 1024*1024)) {
+ return ((addr & T2_MEM_R1_MASK) << 5) + T2_SPARSE_MEM;
+ }
+#if 0
+ printk("T2: address 0x%lx not covered by HAE\n", addr);
+#endif
+ return 0;
+}
+
+__EXTERN_INLINE unsigned long t2_srm_readb(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = t2_srm_base(addr)) == 0)
+ return 0xff;
+ work += 0x00; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long t2_srm_readw(unsigned long addr)
+{
+ unsigned long result, work;
+
+ if ((work = t2_srm_base(addr)) == 0)
+ return 0xffff;
+ work += 0x08; /* add transfer length */
+
+ result = *(vip) work;
+ return __kernel_extwl(result, addr & 3);
+}
+
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
+__EXTERN_INLINE unsigned long t2_srm_readl(unsigned long addr)
+{
+ unsigned long work;
+
+ if ((work = t2_srm_base(addr)) == 0)
+ return 0xffffffff;
+ work += 0x18; /* add transfer length */
+
+ return *(vuip) work;
+}
+
+/* ... which makes me wonder why we advertise we have DENSE memory at all.
+ Anyway, guess that means we should emulate 64-bit access as two cycles. */
+__EXTERN_INLINE unsigned long t2_srm_readq(unsigned long addr)
+{
+ unsigned long work, r0, r1;
+
+ if ((work = t2_srm_base(addr)) == 0)
+ return ~0UL;
+ work += 0x18; /* add transfer length */
+
+ r0 = *(vuip) work;
+ r1 = *(vuip) (work + (4 << 5));
+ return r1 << 32 | r0;
+}
+
+__EXTERN_INLINE void t2_srm_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long work = t2_srm_base(addr);
+ if (work) {
+ work += 0x00; /* add transfer length */
+ *(vuip) work = b * 0x01010101;
+ }
+}
+
+__EXTERN_INLINE void t2_srm_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long work = t2_srm_base(addr);
+ if (work) {
+ work += 0x08; /* add transfer length */
+ *(vuip) work = b * 0x00010001;
+ }
+}
+
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
+__EXTERN_INLINE void t2_srm_writel(unsigned int b, unsigned long addr)
+{
+ unsigned long work = t2_srm_base(addr);
+ if (work) {
+ work += 0x18; /* add transfer length */
+ *(vuip) work = b;
+ }
+}
+
+/* ... which makes me wonder why we advertise we have DENSE memory at all.
+ Anyway, guess that means we should emulate 64-bit access as two cycles. */
+__EXTERN_INLINE void t2_srm_writeq(unsigned long b, unsigned long addr)
+{
+ unsigned long work = t2_srm_base(addr);
+ if (work) {
+ work += 0x18; /* add transfer length */
+ *(vuip) work = b;
+ *(vuip) (work + (4 << 5)) = b >> 32;
+ }
+}
+
+__EXTERN_INLINE unsigned long t2_readb(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00) ;
+ return __kernel_extbl(result, addr & 3);
+}
+
+__EXTERN_INLINE unsigned long t2_readw(unsigned long addr)
+{
+ unsigned long result, msb;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
+ return __kernel_extwl(result, addr & 3);
+}
+
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */
+__EXTERN_INLINE unsigned long t2_readl(unsigned long addr)
+{
+ unsigned long msb;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
+}
+
+__EXTERN_INLINE unsigned long t2_readq(unsigned long addr)
+{
+ unsigned long r0, r1, work, msb;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ work = (addr << 5) + T2_SPARSE_MEM + 0x18;
+ r0 = *(vuip)(work);
+ r1 = *(vuip)(work + (4 << 5));
+ return r1 << 32 | r0;
+}
+
+__EXTERN_INLINE void t2_writeb(unsigned char b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101;
+}
+
+__EXTERN_INLINE void t2_writew(unsigned short b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = b * 0x00010001;
+}
+
+/* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */
+__EXTERN_INLINE void t2_writel(unsigned int b, unsigned long addr)
+{
+ unsigned long msb ;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
+}
+
+__EXTERN_INLINE void t2_writeq(unsigned long b, unsigned long addr)
+{
+ unsigned long msb, work;
+
+ msb = addr & 0xE0000000 ;
+ addr &= T2_MEM_R1_MASK ;
+ set_hae(msb);
+
+ work = (addr << 5) + T2_SPARSE_MEM + 0x18;
+ *(vuip)work = b;
+ *(vuip)(work + (4 << 5)) = b >> 32;
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long t2_dense_mem(unsigned long addr)
+{
+ return T2_DENSE_MEM;
+}
+
+#undef vip
+#undef vuip
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus t2_virt_to_bus
+#define bus_to_virt t2_bus_to_virt
+#define __inb t2_inb
+#define __inw t2_inw
+#define __inl t2_inl
+#define __outb t2_outb
+#define __outw t2_outw
+#define __outl t2_outl
+
+#ifdef CONFIG_ALPHA_SRM_SETUP
+#define __readb t2_srm_readb
+#define __readw t2_srm_readw
+#define __readl t2_srm_readl
+#define __readq t2_srm_readq
+#define __writeb t2_srm_writeb
+#define __writew t2_srm_writew
+#define __writel t2_srm_writel
+#define __writeq t2_srm_writeq
+#else
+#define __readb t2_readb
+#define __readw t2_readw
+#define __readl t2_readl
+#define __readq t2_readq
+#define __writeb t2_writeb
+#define __writew t2_writew
+#define __writel t2_writel
+#define __writeq t2_writeq
+#endif
+
+#define dense_mem t2_dense_mem
+
+#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)))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_T2__H__ */
--- /dev/null
+#ifndef __ALPHA_TSUNAMI__H__
+#define __ALPHA_TSUNAMI__H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/compiler.h>
+
+/*
+ * TSUNAMI/TYPHOON are the internal names for the core logic chipset which
+ * provides memory controller and PCI access for the 21264 based systems.
+ *
+ * This file is based on:
+ *
+ * Tsunami System Programmers Manual
+ * Preliminary, Chapters 2-5
+ *
+ */
+
+#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
+#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+#define TSUNAMI_DMA_WIN_BASE alpha_mv.dma_win_base
+#define TSUNAMI_DMA_WIN_SIZE alpha_mv.dma_win_size
+#else
+#define TSUNAMI_DMA_WIN_BASE TSUNAMI_DMA_WIN_BASE_DEFAULT
+#define TSUNAMI_DMA_WIN_SIZE TSUNAMI_DMA_WIN_SIZE_DEFAULT
+#endif
+
+/* XXX: Do we need to conditionalize on this? */
+#ifdef USE_48_BIT_KSEG
+#define TS_BIAS 0x80000000000UL
+#else
+#define TS_BIAS 0x10000000000UL
+#endif
+
+/*
+ * CChip and DChip registers
+ */
+#define TSUNAMI_CSR_CSC (IDENT_ADDR + TS_BIAS + 0x1A0000000UL)
+#define TSUNAMI_CSR_MTR (IDENT_ADDR + TS_BIAS + 0x1A0000040UL)
+#define TSUNAMI_CSR_MISC (IDENT_ADDR + TS_BIAS + 0x1A0000080UL)
+#define TSUNAMI_CSR_MPD (IDENT_ADDR + TS_BIAS + 0x1A00000C0UL)
+#define TSUNAMI_CSR_AAR0 (IDENT_ADDR + TS_BIAS + 0x1A0000100UL)
+#define TSUNAMI_CSR_AAR1 (IDENT_ADDR + TS_BIAS + 0x1A0000140UL)
+#define TSUNAMI_CSR_AAR2 (IDENT_ADDR + TS_BIAS + 0x1A0000180UL)
+#define TSUNAMI_CSR_AAR3 (IDENT_ADDR + TS_BIAS + 0x1A00001C0UL)
+#define TSUNAMI_CSR_DIM0 (IDENT_ADDR + TS_BIAS + 0x1A0000200UL)
+#define TSUNAMI_CSR_DIM1 (IDENT_ADDR + TS_BIAS + 0x1A0000240UL)
+#define TSUNAMI_CSR_DIR0 (IDENT_ADDR + TS_BIAS + 0x1A0000280UL)
+#define TSUNAMI_CSR_DIR1 (IDENT_ADDR + TS_BIAS + 0x1A00002C0UL)
+
+#define TSUNAMI_CSR_DRIR (IDENT_ADDR + TS_BIAS + 0x1A0000300UL)
+#define TSUNAMI_CSR_PRBEN (IDENT_ADDR + TS_BIAS + 0x1A0000340UL)
+#define TSUNAMI_CSR_IIC (IDENT_ADDR + TS_BIAS + 0x1A0000380UL)
+#define TSUNAMI_CSR_WDR (IDENT_ADDR + TS_BIAS + 0x1A00003C0UL)
+#define TSUNAMI_CSR_MPR0 (IDENT_ADDR + TS_BIAS + 0x1A0000400UL)
+#define TSUNAMI_CSR_MPR1 (IDENT_ADDR + TS_BIAS + 0x1A0000440UL)
+#define TSUNAMI_CSR_MPR2 (IDENT_ADDR + TS_BIAS + 0x1A0000480UL)
+#define TSUNAMI_CSR_MPR3 (IDENT_ADDR + TS_BIAS + 0x1A00004C0UL)
+#define TSUNAMI_CSR_TTR (IDENT_ADDR + TS_BIAS + 0x1A0000580UL)
+#define TSUNAMI_CSR_TDR (IDENT_ADDR + TS_BIAS + 0x1A00005C0UL)
+#define TSUNAMI_CSR_DSC (IDENT_ADDR + TS_BIAS + 0x1B0000800UL)
+#define TSUNAMI_CSR_STR (IDENT_ADDR + TS_BIAS + 0x1B0000840UL)
+#define TSUNAMI_CSR_DREV (IDENT_ADDR + TS_BIAS + 0x1B0000880UL)
+
+/*
+ * PChip registers
+ */
+#define TSUNAMI_PCHIP0_WSBA0 (IDENT_ADDR + TS_BIAS + 0x180000000UL)
+#define TSUNAMI_PCHIP0_WSBA1 (IDENT_ADDR + TS_BIAS + 0x180000040UL)
+#define TSUNAMI_PCHIP0_WSBA2 (IDENT_ADDR + TS_BIAS + 0x180000080UL)
+#define TSUNAMI_PCHIP0_WSBA3 (IDENT_ADDR + TS_BIAS + 0x1800000C0UL)
+
+#define TSUNAMI_PCHIP0_WSM0 (IDENT_ADDR + TS_BIAS + 0x180000100UL)
+#define TSUNAMI_PCHIP0_WSM1 (IDENT_ADDR + TS_BIAS + 0x180000140UL)
+#define TSUNAMI_PCHIP0_WSM2 (IDENT_ADDR + TS_BIAS + 0x180000180UL)
+#define TSUNAMI_PCHIP0_WSM3 (IDENT_ADDR + TS_BIAS + 0x1800001C0UL)
+#define TSUNAMI_PCHIP0_TBA0 (IDENT_ADDR + TS_BIAS + 0x180000200UL)
+#define TSUNAMI_PCHIP0_TBA1 (IDENT_ADDR + TS_BIAS + 0x180000240UL)
+#define TSUNAMI_PCHIP0_TBA2 (IDENT_ADDR + TS_BIAS + 0x180000280UL)
+#define TSUNAMI_PCHIP0_TBA3 (IDENT_ADDR + TS_BIAS + 0x1800002C0UL)
+
+#define TSUNAMI_PCHIP0_PCTL (IDENT_ADDR + TS_BIAS + 0x180000300UL)
+#define TSUNAMI_PCHIP0_PLAT (IDENT_ADDR + TS_BIAS + 0x180000340UL)
+#define TSUNAMI_PCHIP0_RESERVED (IDENT_ADDR + TS_BIAS + 0x180000380UL)
+#define TSUNAMI_PCHIP0_PERROR (IDENT_ADDR + TS_BIAS + 0x1800003c0UL)
+#define TSUNAMI_PCHIP0_PERRMASK (IDENT_ADDR + TS_BIAS + 0x180000400UL)
+#define TSUNAMI_PCHIP0_PERRSET (IDENT_ADDR + TS_BIAS + 0x180000440UL)
+#define TSUNAMI_PCHIP0_TLBIV (IDENT_ADDR + TS_BIAS + 0x180000480UL)
+#define TSUNAMI_PCHIP0_TLBIA (IDENT_ADDR + TS_BIAS + 0x1800004C0UL)
+#define TSUNAMI_PCHIP0_PMONCTL (IDENT_ADDR + TS_BIAS + 0x180000500UL)
+#define TSUNAMI_PCHIP0_PMONCNT (IDENT_ADDR + TS_BIAS + 0x180000540UL)
+
+#define TSUNAMI_PCHIP1_WSBA0 (IDENT_ADDR + TS_BIAS + 0x380000000UL)
+#define TSUNAMI_PCHIP1_WSBA1 (IDENT_ADDR + TS_BIAS + 0x380000040UL)
+#define TSUNAMI_PCHIP1_WSBA2 (IDENT_ADDR + TS_BIAS + 0x380000080UL)
+#define TSUNAMI_PCHIP1_WSBA3 (IDENT_ADDR + TS_BIAS + 0x3800000C0UL)
+#define TSUNAMI_PCHIP1_WSM0 (IDENT_ADDR + TS_BIAS + 0x380000100UL)
+#define TSUNAMI_PCHIP1_WSM1 (IDENT_ADDR + TS_BIAS + 0x380000140UL)
+#define TSUNAMI_PCHIP1_WSM2 (IDENT_ADDR + TS_BIAS + 0x380000180UL)
+#define TSUNAMI_PCHIP1_WSM3 (IDENT_ADDR + TS_BIAS + 0x3800001C0UL)
+
+#define TSUNAMI_PCHIP1_TBA0 (IDENT_ADDR + TS_BIAS + 0x380000200UL)
+#define TSUNAMI_PCHIP1_TBA1 (IDENT_ADDR + TS_BIAS + 0x380000240UL)
+#define TSUNAMI_PCHIP1_TBA2 (IDENT_ADDR + TS_BIAS + 0x380000280UL)
+#define TSUNAMI_PCHIP1_TBA3 (IDENT_ADDR + TS_BIAS + 0x3800002C0UL)
+
+#define TSUNAMI_PCHIP1_PCTL (IDENT_ADDR + TS_BIAS + 0x380000300UL)
+#define TSUNAMI_PCHIP1_PLAT (IDENT_ADDR + TS_BIAS + 0x380000340UL)
+#define TSUNAMI_PCHIP1_RESERVED (IDENT_ADDR + TS_BIAS + 0x380000380UL)
+#define TSUNAMI_PCHIP1_PERROR (IDENT_ADDR + TS_BIAS + 0x3800003c0UL)
+#define TSUNAMI_PCHIP1_PERRMASK (IDENT_ADDR + TS_BIAS + 0x380000400UL)
+#define TSUNAMI_PCHIP1_PERRSET (IDENT_ADDR + TS_BIAS + 0x380000440UL)
+#define TSUNAMI_PCHIP1_TLBIV (IDENT_ADDR + TS_BIAS + 0x380000480UL)
+#define TSUNAMI_PCHIP1_TLBIA (IDENT_ADDR + TS_BIAS + 0x3800004C0UL)
+#define TSUNAMI_PCHIP1_PMONCTL (IDENT_ADDR + TS_BIAS + 0x380000500UL)
+#define TSUNAMI_PCHIP1_PMONCNT (IDENT_ADDR + TS_BIAS + 0x380000540UL)
+
+/* */
+/* TSUNAMI Pchip Error register. */
+/* */
+#define perror_m_lost 0x1
+#define perror_m_serr 0x2
+#define perror_m_perr 0x4
+#define perror_m_dcrto 0x8
+#define perror_m_sge 0x10
+#define perror_m_ape 0x20
+#define perror_m_ta 0x40
+#define perror_m_rdpe 0x80
+#define perror_m_nds 0x100
+#define perror_m_rto 0x200
+#define perror_m_uecc 0x400
+#define perror_m_cre 0x800
+#define perror_m_addrl 0xFFFFFFFF0000UL
+#define perror_m_addrh 0x7000000000000UL
+#define perror_m_cmd 0xF0000000000000UL
+#define perror_m_syn 0xFF00000000000000UL
+union TPchipPERROR {
+ struct {
+ unsigned int perror_v_lost : 1;
+ unsigned perror_v_serr : 1;
+ unsigned perror_v_perr : 1;
+ unsigned perror_v_dcrto : 1;
+ unsigned perror_v_sge : 1;
+ unsigned perror_v_ape : 1;
+ unsigned perror_v_ta : 1;
+ unsigned perror_v_rdpe : 1;
+ unsigned perror_v_nds : 1;
+ unsigned perror_v_rto : 1;
+ unsigned perror_v_uecc : 1;
+ unsigned perror_v_cre : 1;
+ unsigned perror_v_rsvd1 : 4;
+ unsigned perror_v_addrl : 32;
+ unsigned perror_v_addrh : 3;
+ unsigned perror_v_rsvd2 : 1;
+ unsigned perror_v_cmd : 4;
+ unsigned perror_v_syn : 8;
+ } perror_r_bits;
+ int perror_q_whole [2];
+ } ;
+/* */
+/* TSUNAMI Pchip Window Space Base Address register. */
+/* */
+#define wsba_m_ena 0x1
+#define wsba_m_sg 0x2
+#define wsba_m_ptp 0x4
+#define wsba_m_addr 0xFFF00000
+#define wmask_k_sz1gb 0x3FF00000
+union TPchipWSBA {
+ struct {
+ unsigned wsba_v_ena : 1;
+ unsigned wsba_v_sg : 1;
+ unsigned wsba_v_ptp : 1;
+ unsigned wsba_v_rsvd1 : 17;
+ unsigned wsba_v_addr : 12;
+ unsigned wsba_v_rsvd2 : 32;
+ } wsba_r_bits;
+ int wsba_q_whole [2];
+ } ;
+/* */
+/* TSUNAMI Pchip Control Register */
+/* */
+#define pctl_m_fdsc 0x1
+#define pctl_m_fbtb 0x2
+#define pctl_m_thdis 0x4
+#define pctl_m_chaindis 0x8
+#define pctl_m_tgtlat 0x10
+#define pctl_m_hole 0x20
+#define pctl_m_mwin 0x40
+#define pctl_m_arbena 0x80
+#define pctl_m_prigrp 0x7F00
+#define pctl_m_ppri 0x8000
+#define pctl_m_rsvd1 0x30000
+#define pctl_m_eccen 0x40000
+#define pctl_m_padm 0x80000
+#define pctl_m_cdqmax 0xF00000
+#define pctl_m_rev 0xFF000000
+#define pctl_m_crqmax 0xF00000000UL
+#define pctl_m_ptpmax 0xF000000000UL
+#define pctl_m_pclkx 0x30000000000UL
+#define pctl_m_fdsdis 0x40000000000UL
+#define pctl_m_fdwdis 0x80000000000UL
+#define pctl_m_ptevrfy 0x100000000000UL
+#define pctl_m_rpp 0x200000000000UL
+#define pctl_m_pid 0xC00000000000UL
+#define pctl_m_rsvd2 0xFFFF000000000000UL
+
+union TPchipPCTL {
+ struct {
+ unsigned pctl_v_fdsc : 1;
+ unsigned pctl_v_fbtb : 1;
+ unsigned pctl_v_thdis : 1;
+ unsigned pctl_v_chaindis : 1;
+ unsigned pctl_v_tgtlat : 1;
+ unsigned pctl_v_hole : 1;
+ unsigned pctl_v_mwin : 1;
+ unsigned pctl_v_arbena : 1;
+ unsigned pctl_v_prigrp : 7;
+ unsigned pctl_v_ppri : 1;
+ unsigned pctl_v_rsvd1 : 2;
+ unsigned pctl_v_eccen : 1;
+ unsigned pctl_v_padm : 1;
+ unsigned pctl_v_cdqmax : 4;
+ unsigned pctl_v_rev : 8;
+ unsigned pctl_v_crqmax : 4;
+ unsigned pctl_v_ptpmax : 4;
+ unsigned pctl_v_pclkx : 2;
+ unsigned pctl_v_fdsdis : 1;
+ unsigned pctl_v_fdwdis : 1;
+ unsigned pctl_v_ptevrfy : 1;
+ unsigned pctl_v_rpp : 1;
+ unsigned pctl_v_pid : 2;
+ unsigned pctl_v_rsvd2 : 16;
+ } pctl_r_bits;
+ int pctl_q_whole [2];
+} ;
+/* */
+/* TSUNAMI Pchip Error Mask Register. */
+/* */
+#define perrmask_m_lost 0x1
+#define perrmask_m_serr 0x2
+#define perrmask_m_perr 0x4
+#define perrmask_m_dcrto 0x8
+#define perrmask_m_sge 0x10
+#define perrmask_m_ape 0x20
+#define perrmask_m_ta 0x40
+#define perrmask_m_rdpe 0x80
+#define perrmask_m_nds 0x100
+#define perrmask_m_rto 0x200
+#define perrmask_m_uecc 0x400
+#define perrmask_m_cre 0x800
+#define perrmask_m_rsvd 0xFFFFFFFFFFFFF000UL
+union TPchipPERRMASK {
+ struct {
+ unsigned int perrmask_v_lost : 1;
+ unsigned perrmask_v_serr : 1;
+ unsigned perrmask_v_perr : 1;
+ unsigned perrmask_v_dcrto : 1;
+ unsigned perrmask_v_sge : 1;
+ unsigned perrmask_v_ape : 1;
+ unsigned perrmask_v_ta : 1;
+ unsigned perrmask_v_rdpe : 1;
+ unsigned perrmask_v_nds : 1;
+ unsigned perrmask_v_rto : 1;
+ unsigned perrmask_v_uecc : 1;
+ unsigned perrmask_v_cre : 1;
+ unsigned perrmask_v_rsvd1 : 20;
+ unsigned perrmask_v_rsvd2 : 32;
+ } perrmask_r_bits;
+ int perrmask_q_whole [2];
+ } ;
+
+/*
+ * Memory spaces:
+ */
+#define TSUNAMI_PCI0_MEM (IDENT_ADDR + TS_BIAS + 0x000000000UL)
+#define TSUNAMI_PCI0_IACK_SC (IDENT_ADDR + TS_BIAS + 0x1F8000000UL)
+#define TSUNAMI_PCI0_IO (IDENT_ADDR + TS_BIAS + 0x1FC000000UL)
+#define TSUNAMI_PCI0_CONF (IDENT_ADDR + TS_BIAS + 0x1FE000000UL)
+
+#define TSUNAMI_PCI1_MEM (IDENT_ADDR + TS_BIAS + 0x200000000UL)
+#define TSUNAMI_PCI1_IACK_SC (IDENT_ADDR + TS_BIAS + 0x3F8000000UL)
+#define TSUNAMI_PCI1_IO (IDENT_ADDR + TS_BIAS + 0x3FC000000UL)
+#define TSUNAMI_PCI1_CONF (IDENT_ADDR + TS_BIAS + 0x3FE000000UL)
+
+/*
+ * Data structure for handling TSUNAMI machine checks:
+ */
+struct el_TSUNAMI_sysdata_mcheck {
+};
+
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+__EXTERN_INLINE unsigned long tsunami_virt_to_bus(void * address)
+{
+ return virt_to_phys(address) + TSUNAMI_DMA_WIN_BASE;
+}
+
+__EXTERN_INLINE void * tsunami_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * TSUNAMI, the 21??? PCI/memory support chipset for the EV6 (21264)
+ * can only use linear accesses to get at PCI memory and I/O spaces.
+ */
+
+/* HACK ALERT! HACK ALERT! */
+/* HACK ALERT! HACK ALERT! */
+
+/* Only using PCI bus 0 for now in all routines. */
+
+#define TSUNAMI_IACK_SC TSUNAMI_PCI0_IACK_SC
+
+/* HACK ALERT! HACK ALERT! */
+/* HACK ALERT! HACK ALERT! */
+
+#define vucp volatile unsigned char *
+#define vusp volatile unsigned short *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+__EXTERN_INLINE unsigned int tsunami_inb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr + TSUNAMI_PCI0_IO));
+}
+
+__EXTERN_INLINE void tsunami_outb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr + TSUNAMI_PCI0_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int tsunami_inw(unsigned long addr)
+{
+ return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_IO));
+}
+
+__EXTERN_INLINE void tsunami_outw(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_IO));
+ mb();
+}
+
+__EXTERN_INLINE unsigned int tsunami_inl(unsigned long addr)
+{
+ return *(vuip)(addr+TSUNAMI_PCI0_IO);
+}
+
+__EXTERN_INLINE void tsunami_outl(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+TSUNAMI_PCI0_IO) = b;
+ mb();
+}
+
+/*
+ * Memory functions. all accesses are done through linear space.
+ */
+
+__EXTERN_INLINE unsigned long tsunami_readb(unsigned long addr)
+{
+ return __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_MEM));
+}
+
+__EXTERN_INLINE unsigned long tsunami_readw(unsigned long addr)
+{
+ return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_MEM));
+}
+
+__EXTERN_INLINE unsigned long tsunami_readl(unsigned long addr)
+{
+ return *(vuip)(addr+TSUNAMI_PCI0_MEM);
+}
+
+__EXTERN_INLINE unsigned long tsunami_readq(unsigned long addr)
+{
+ return *(vulp)(addr+TSUNAMI_PCI0_MEM);
+}
+
+__EXTERN_INLINE void tsunami_writeb(unsigned char b, unsigned long addr)
+{
+ __kernel_stb(b, *(vucp)(addr+TSUNAMI_PCI0_MEM));
+ mb();
+}
+
+__EXTERN_INLINE void tsunami_writew(unsigned short b, unsigned long addr)
+{
+ __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_MEM));
+ mb();
+}
+
+__EXTERN_INLINE void tsunami_writel(unsigned int b, unsigned long addr)
+{
+ *(vuip)(addr+TSUNAMI_PCI0_MEM) = b;
+ mb();
+}
+
+__EXTERN_INLINE void tsunami_writeq(unsigned long b, unsigned long addr)
+{
+ *(vulp)(addr+TSUNAMI_PCI0_MEM) = b;
+ mb();
+}
+
+/* Find the DENSE memory area for a given bus address. */
+
+__EXTERN_INLINE unsigned long tsunami_dense_mem(unsigned long addr)
+{
+ return TSUNAMI_PCI0_MEM;
+}
+
+#undef vucp
+#undef vusp
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus tsunami_virt_to_bus
+#define bus_to_virt tsunami_bus_to_virt
+
+#define __inb tsunami_inb
+#define __inw tsunami_inw
+#define __inl tsunami_inl
+#define __outb tsunami_outb
+#define __outw tsunami_outw
+#define __outl tsunami_outl
+#define __readb tsunami_readb
+#define __readw tsunami_readw
+#define __writeb tsunami_writeb
+#define __writew tsunami_writew
+#define __readl tsunami_readl
+#define __readq tsunami_readq
+#define __writel tsunami_writel
+#define __writeq tsunami_writeq
+#define dense_mem tsunami_dense_mem
+
+#define inb(port) __inb((port))
+#define inw(port) __inw((port))
+#define inl(port) __inl((port))
+
+#define outb(v, port) __outb((v),(port))
+#define outw(v, port) __outw((v),(port))
+#define outl(v, port) __outl((v),(port))
+
+#define readb(a) __readb((unsigned long)(a))
+#define readw(a) __readw((unsigned long)(a))
+#define readl(a) __readl((unsigned long)(a))
+#define readq(a) __readq((unsigned long)(a))
+
+#define writeb(v,a) __writeb((v),(unsigned long)(a))
+#define writew(v,a) __writew((v),(unsigned long)(a))
+#define writel(v,a) __writel((v),(unsigned long)(a))
+#define writeq(v,a) __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_TSUNAMI__H__ */
#define _ASM_DMA_H
#include <linux/config.h>
-
-#include <asm/io.h> /* need byte IO */
+#include <asm/io.h>
#define dma_outb outb
#define dma_inb inb
#define MAX_DMA_CHANNELS 8
-#ifdef CONFIG_ALPHA_XL
/* The maximum address that we can perform a DMA transfer to on Alpha XL,
due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 64MB.
See <asm/apecs.h> for more info.
We MUST coordinate the maximum with <asm/apecs.h> for consistency.
For now, this limit is set to 48Mb...
*/
-#define MAX_DMA_ADDRESS (0xfffffc0003000000UL)
-#else /* CONFIG_ALPHA_XL */
-/* The maximum address that we can perform a DMA transfer to on normal
- Alpha platforms */
-#define MAX_DMA_ADDRESS (~0UL)
-#endif /* CONFIG_ALPHA_XL */
+#define ALPHA_XL_MAX_DMA_ADDRESS (0xfffffc0003000000UL)
+#define ALPHA_MAX_DMA_ADDRESS (~0UL)
+
+#ifdef CONFIG_ALPHA_GENERIC
+# define MAX_DMA_ADDRESS (alpha_mv.max_dma_address)
+#else
+# ifdef CONFIG_ALPHA_XL
+# define MAX_DMA_ADDRESS ALPHA_XL_MAX_DMA_ADDRESS
+# else
+# define MAX_DMA_ADDRESS ALPHA_MAX_DMA_ADDRESS
+# endif
+#endif
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
#define FLOPPY_MOTOR_MASK 0xf0
/*
- * Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh...
+ * Most Alphas have no problems with floppy DMA crossing 64k borders,
+ * except for XL. It is also the only one with DMA limits, so we use
+ * that to test in the generic kernel.
*/
-#ifdef CONFIG_ALPHA_XL
-#define CROSS_64KB(a,s) \
- ((unsigned long)(a)/0x10000 != ((unsigned long)(a) + (s) - 1) / 0x10000)
-#else /* CONFIG_ALPHA_XL */
-#define CROSS_64KB(a,s) (0)
-#endif /* CONFIG_ALPHA_XL */
+
+#define __CROSS_64KB(a,s) \
+({ unsigned long __s64 = (unsigned long)(a); \
+ unsigned long __e64 = __s64 + (unsigned long)(s) - 1; \
+ (__s64 ^ __e64) & ~0xfffful; })
+
+#ifdef CONFIG_ALPHA_GENERIC
+# define CROSS_64KB(a,s) (__CROSS_64KB(a,s) && ~alpha_mv.max_dma_address)
+#else
+# ifdef CONFIG_ALPHA_XL
+# define CROSS_64KB(a,s) __CROSS_64KB(a,s)
+# else
+# define CROSS_64KB(a,s) (0)
+# endif
+#endif
#endif /* __ASM_ALPHA_FLOPPY_H */
-#ifndef _HWRPB_H
-#define _HWRPB_H
+#ifndef __ALPHA_HWRPB_H
+#define __ALPHA_HWRPB_H
#define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000)
#define ST_DEC_AXPPCI_33 11 /* NoName system type */
#define ST_DEC_TLASER 12 /* Turbolaser systype */
#define ST_DEC_2100_A50 13 /* Avanti systype */
+#define ST_DEC_MUSTANG 14 /* Mustang systype */
#define ST_DEC_ALCOR 15 /* Alcor (EV5) systype */
#define ST_DEC_1000 17 /* Mikasa systype */
#define ST_DEC_EB64 18 /* EB64 systype */
unsigned long halt_pv;
unsigned long halt_reason;
unsigned long res;
- unsigned long ipc_buffer[21];
+ char ipc_buffer[168];
unsigned long palcode_avail[16];
unsigned long compatibility;
};
unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */
};
-#endif
+extern struct hwrpb_struct *hwrpb;
+
+#endif /* __ALPHA_HWRPB_H */
__arginit __init; \
__arginit
-#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8
-#define __initlocaldata __initdata
-#else
-#define __initlocaldata
-#endif
-
/* For assembly routines */
#define __INIT .section .text.init,"ax"
#define __FINIT .previous
#define __ALPHA_IO_H
#include <linux/config.h>
-
#include <asm/system.h>
+#include <asm/machvec.h>
/* We don't use IO slowdowns on the Alpha, but.. */
#define __SLOW_DOWN_IO do { } while (0)
#define SLOW_DOWN_IO do { } while (0)
-/*
- * The hae (hardware address extension) register is used to
- * access high IO addresses. To avoid doing an external cycle
- * every time we need to set the hae, we have a hae cache in
- * memory. The kernel entry code makes sure that the hae is
- * preserved across interrupts, so it is safe to set the hae
- * once and then depend on it staying the same in kernel code.
- */
-extern struct hae {
- unsigned long cache;
- unsigned long *reg;
-} hae;
-
/*
* Virtual -> physical identity mapping starts at this offset
*/
+/* XXX: Do we need to conditionalize on this? */
#ifdef USE_48_BIT_KSEG
#define IDENT_ADDR (0xffff800000000000UL)
#else
* register not being up-to-date with respect to the hardware
* value.
*/
-extern inline void set_hae(unsigned long new_hae)
+static inline void __set_hae(unsigned long new_hae)
{
unsigned long ipl = swpipl(7);
- hae.cache = new_hae;
- *hae.reg = new_hae;
+
+ alpha_mv.hae_cache = new_hae;
+ *alpha_mv.hae_register = new_hae;
mb();
- new_hae = *hae.reg; /* read to make sure it was written */
+
+ /* Re-read to make sure it was written. */
+ new_hae = *alpha_mv.hae_register;
setipl(ipl);
}
+static inline void set_hae(unsigned long new_hae)
+{
+ if (new_hae != alpha_mv.hae_cache)
+ __set_hae(new_hae);
+}
+
/*
* Change virtual addresses to physical addresses and vv.
*/
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
{
return 0xffffffffUL & (unsigned long) address;
}
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
{
return (void *) (address + IDENT_ADDR);
}
#endif /* !__KERNEL__ */
/*
- * EGCS 1.1 does a good job of using insxl. Expose this bit of
- * the I/O process to the compiler.
+ * There are different chipsets to interface the Alpha CPUs to the world.
*/
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
-# define __kernel_insbl(val, shift) (((val) & 0xfful) << ((shift) * 8))
-# define __kernel_inswl(val, shift) (((val) & 0xfffful) << ((shift) * 8))
+#ifdef CONFIG_ALPHA_GENERIC
+
+/* In a generic kernel, we always go through the machine vector. */
+
+# define virt_to_bus(a) alpha_mv.mv_virt_to_bus(a)
+# define bus_to_virt(a) alpha_mv.mv_bus_to_virt(a)
+
+# define __inb alpha_mv.mv_inb
+# define __inw alpha_mv.mv_inw
+# define __inl alpha_mv.mv_inl
+# define __outb alpha_mv.mv_outb
+# define __outw alpha_mv.mv_outw
+# define __outl alpha_mv.mv_outl
+
+# define __readb(a) alpha_mv.mv_readb((unsigned long)(a))
+# define __readw(a) alpha_mv.mv_readw((unsigned long)(a))
+# define __readl(a) alpha_mv.mv_readl((unsigned long)(a))
+# define __readq(a) alpha_mv.mv_readq((unsigned long)(a))
+# define __writeb(v,a) alpha_mv.mv_writeb((v),(unsigned long)(a))
+# define __writew(v,a) alpha_mv.mv_writew((v),(unsigned long)(a))
+# define __writel(v,a) alpha_mv.mv_writel((v),(unsigned long)(a))
+# define __writeq(v,a) alpha_mv.mv_writeq((v),(unsigned long)(a))
+
+# define inb __inb
+# define inw __inw
+# define inl __inl
+# define outb __outb
+# define outw __outw
+# define outl __outl
+
+# define readb __readb
+# define readw __readw
+# define readl __readl
+# define readq __readq
+# define writeb __writeb
+# define writew __writew
+# define writel __writel
+# define writeq __writeq
+
+# define dense_mem(a) alpha_mv.mv_dense_mem(a)
+
#else
-# define __kernel_insbl(val, shift) \
- ({ unsigned long __kir; \
- __asm__("insbl %2,%1,%0" : "=r"(__kir) : "ri"(shift), "r"(val)); \
- __kir; })
-# define __kernel_inswl(val, shift) \
- ({ unsigned long __kir; \
- __asm__("inswl %2,%1,%0" : "=r"(__kir) : "ri"(shift), "r"(val)); \
- __kir; })
-#endif
-
-/*
- * There are different chipsets to interface the Alpha CPUs to the world.
- */
-#if defined(CONFIG_ALPHA_LCA)
-# include <asm/lca.h> /* get chip-specific definitions */
-#elif defined(CONFIG_ALPHA_APECS)
-# include <asm/apecs.h> /* get chip-specific definitions */
+
+/* Control how and what gets defined within the core logic headers. */
+#define __WANT_IO_DEF
+
+#if defined(CONFIG_ALPHA_APECS)
+# include <asm/core_apecs.h>
#elif defined(CONFIG_ALPHA_CIA)
-# include <asm/cia.h> /* get chip-specific definitions */
-#elif defined(CONFIG_ALPHA_T2)
-# include <asm/t2.h> /* get chip-specific definitions */
+# include <asm/core_cia.h>
+#elif defined(CONFIG_ALPHA_LCA)
+# include <asm/core_lca.h>
+#elif defined(CONFIG_ALPHA_MCPCIA)
+# include <asm/core_mcpcia.h>
#elif defined(CONFIG_ALPHA_PYXIS)
-# include <asm/pyxis.h> /* get chip-specific definitions */
+# include <asm/core_pyxis.h>
+#elif defined(CONFIG_ALPHA_T2)
+# include <asm/core_t2.h>
#elif defined(CONFIG_ALPHA_TSUNAMI)
-# include <asm/tsunami.h> /* get chip-specific definitions */
-#elif defined(CONFIG_ALPHA_MCPCIA)
-# include <asm/mcpcia.h> /* get chip-specific definitions */
-#else
+# include <asm/core_tsunami.h>
+#elif defined(CONFIG_ALPHA_JENSEN)
# include <asm/jensen.h>
+#else
+#error "What system is this?"
#endif
+#undef __WANT_IO_DEF
+
+#endif /* GENERIC */
+
/*
* The convention used for inb/outb etc. is that names starting with
* two underscores are the inline versions, names starting with a
* On the alpha, we have the whole physical address space mapped at all
* times, so "ioremap()" and "iounmap()" do not need to do anything.
*/
-extern inline void * ioremap(unsigned long offset, unsigned long size)
+static inline void * ioremap(unsigned long offset, unsigned long size)
{
return (void *) offset;
}
-extern inline void iounmap(void *addr)
+static inline void iounmap(void *addr)
{
}
#define eth_io_copy_and_sum(skb,src,len,unused) \
memcpy_fromio((skb)->data,(src),(len))
-static inline int check_signature(unsigned long io_addr,
- const unsigned char *signature, int length)
+static inline int
+check_signature(unsigned long io_addr, const unsigned char *signature,
+ int length)
{
int retval = 0;
do {
return retval;
}
-#endif /* __KERNEL__ */
+/*
+ * The Alpha Jensen hardware for some rather strange reason puts
+ * the RTC clock at 0x170 instead of 0x70. Probably due to some
+ * misguided idea about using 0x70 for NMI stuff.
+ *
+ * These defines will override the defaults when doing RTC queries
+ */
+#ifdef CONFIG_ALPHA_GENERIC
+# define RTC_PORT(x) ((x) + alpha_mv.rtc_port)
+# define RTC_ADDR(x) ((x) | alpha_mv.rtc_addr)
+#else
+# ifdef CONFIG_ALPHA_JENSEN
+# define RTC_PORT(x) (0x170+(x))
+# define RTC_ADDR(x) (x)
+# else
+# define RTC_PORT(x) (0x70 + (x))
+# define RTC_ADDR(x) (0x80 | (x))
+# endif
#endif
+
+#define RTC_ALWAYS_BCD 0
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_IO_H */
#include <linux/linkage.h>
#include <linux/config.h>
-#if defined(CONFIG_ALPHA_CABRIOLET) || \
+#if defined(CONFIG_ALPHA_GENERIC)
+
+/* Here NR_IRQS is not exact, but rather an upper bound. This is used
+ many places throughout the kernel to size static arrays. That's ok,
+ we'll use alpha_mv.nr_irqs when we want the real thing. */
+
+# define NR_IRQS 64
+
+#elif defined(CONFIG_ALPHA_CABRIOLET) || \
defined(CONFIG_ALPHA_EB66P) || \
defined(CONFIG_ALPHA_EB164) || \
defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164)
-
+ defined(CONFIG_ALPHA_LX164)
# define NR_IRQS 35
#elif defined(CONFIG_ALPHA_EB66) || \
defined(CONFIG_ALPHA_EB64P) || \
- defined(CONFIG_ALPHA_MIKASA)
-
+ defined(CONFIG_ALPHA_MIKASA)
# define NR_IRQS 32
#elif defined(CONFIG_ALPHA_ALCOR) || \
defined(CONFIG_ALPHA_MIATA) || \
defined(CONFIG_ALPHA_RUFFIAN) || \
defined(CONFIG_ALPHA_NORITAKE)
-
# define NR_IRQS 48
#elif defined(CONFIG_ALPHA_SABLE) || \
defined(CONFIG_ALPHA_SX164)
-
# define NR_IRQS 40
#elif defined(CONFIG_ALPHA_DP264) || \
defined(CONFIG_ALPHA_RAWHIDE)
-
# define NR_IRQS 64
#elif defined(CONFIG_ALPHA_TAKARA)
-
# define NR_IRQS 20
#else /* everyone else */
-
# define NR_IRQS 16
+#endif
+
+/*
+ * PROBE_MASK is the bitset of irqs that we consider for autoprobing.
+ */
+
+/* The normal mask includes all the IRQs except the timer. */
+#define _PROBE_MASK(nr_irqs) (((1UL << (nr_irqs & 63)) - 1) & ~1UL)
+/* Mask out unused timer irq 0 and RTC irq 8. */
+#define P2K_PROBE_MASK (_PROBE_MASK(16) & ~0x101UL)
+
+/* Mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade. */
+#define ALCOR_PROBE_MASK (_PROBE_MASK(48) & ~0xfff000000001UL)
+
+/* Leave timer irq 0 in the mask. */
+#define RUFFIAN_PROBE_MASK (_PROBE_MASK(48) | 1UL)
+
+#if defined(CONFIG_ALPHA_GENERIC)
+# define PROBE_MASK alpha_mv.irq_probe_mask
+#elif defined(CONFIG_ALPHA_P2K)
+# define PROBE_MASK P2K_PROBE_MASK
+#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
+# define PROBE_MASK ALCOR_PROBE_MASK
+#elif defined(CONFIG_ALPHA_RUFFIAN)
+# define PROBE_MASK RUFFIAN_PROBE_MASK
+#else
+# define PROBE_MASK _PROBE_MASK(NR_IRQS)
#endif
+
static __inline__ int irq_cannonicalize(int irq)
{
/*
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
-#endif
+#endif /* _ALPHA_IRQ_H */
#ifndef __ALPHA_JENSEN_H
#define __ALPHA_JENSEN_H
+#include <asm/compiler.h>
+
/*
* Defines for the AlphaPC EISA IO and memory address space.
*/
*/
#define EISA_IO (IDENT_ADDR + 0x300000000UL)
+
+#ifdef __KERNEL__
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __IO_EXTERN_INLINE
+#endif
+
/*
* Change virtual addresses to bus addresses and vv.
*
* as the bus address, but this is not necessarily true on
* other alpha hardware.
*/
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
+__EXTERN_INLINE unsigned long jensen_virt_to_bus(void * address)
+{
+ return virt_to_phys(address);
+}
+
+__EXTERN_INLINE void * jensen_bus_to_virt(unsigned long address)
+{
+ return phys_to_virt(address);
+}
-#define HAE_ADDRESS EISA_HAE
/*
* Handle the "host address register". This needs to be set
*
* HAE isn't needed for the local IO operations, though.
*/
-#define __HAE_MASK 0x1ffffff
-extern inline void __set_hae(unsigned long addr)
+
+#define JENSEN_HAE_ADDRESS EISA_HAE
+#define JENSEN_HAE_MASK 0x1ffffff
+
+__EXTERN_INLINE void jensen_set_hae(unsigned long addr)
{
/* hae on the Jensen is bits 31:25 shifted right */
addr >>= 25;
- if (addr != hae.cache)
+ if (addr != alpha_mv.hae_cache)
set_hae(addr);
}
-#ifdef __KERNEL__
+#define vuip volatile unsigned int *
/*
* IO functions
* gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
* convinced that I need one of the newer machines.
*/
-extern inline unsigned int __local_inb(unsigned long addr)
+
+static inline unsigned int jensen_local_inb(unsigned long addr)
{
- long result = *(volatile int *) ((addr << 9) + EISA_VL82C106);
- return 0xffUL & result;
+ return 0xff & *(vuip)((addr << 9) + EISA_VL82C106);
}
-extern inline void __local_outb(unsigned char b, unsigned long addr)
+static inline void jensen_local_outb(unsigned char b, unsigned long addr)
{
- *(volatile unsigned int *) ((addr << 9) + EISA_VL82C106) = b;
+ *(vuip)((addr << 9) + EISA_VL82C106) = b;
mb();
}
-extern unsigned int _bus_inb(unsigned long addr);
-
-extern inline unsigned int __bus_inb(unsigned long addr)
+static inline unsigned int jensen_bus_inb(unsigned long addr)
{
long result;
- __set_hae(0);
- result = *(volatile int *) ((addr << 7) + EISA_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
+ jensen_set_hae(0);
+ result = *(volatile int *)((addr << 7) + EISA_IO + 0x00);
+ return __kernel_extbl(result, addr & 3);
}
-extern void _bus_outb(unsigned char b, unsigned long addr);
-
-extern inline void __bus_outb(unsigned char b, unsigned long addr)
+static inline void jensen_bus_outb(unsigned char b, unsigned long addr)
{
- __set_hae(0);
- *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
+ jensen_set_hae(0);
+ *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
mb();
}
* operations that result in operations across inline functions.
* Which is why this is a macro.
*/
-#define __is_local(addr) ( \
+
+#define jensen_is_local(addr) ( \
/* keyboard */ (addr == 0x60 || addr == 0x64) || \
/* RTC */ (addr == 0x170 || addr == 0x171) || \
/* mb COM2 */ (addr >= 0x2f8 && addr <= 0x2ff) || \
/* mb LPT1 */ (addr >= 0x3bc && addr <= 0x3be) || \
/* mb COM2 */ (addr >= 0x3f8 && addr <= 0x3ff))
-extern inline unsigned int __inb(unsigned long addr)
+__EXTERN_INLINE unsigned int jensen_inb(unsigned long addr)
{
- if (__is_local(addr))
- return __local_inb(addr);
- return _bus_inb(addr);
+ if (jensen_is_local(addr))
+ return jensen_local_inb(addr);
+ else
+ return jensen_bus_inb(addr);
}
-extern inline void __outb(unsigned char b, unsigned long addr)
+__EXTERN_INLINE void jensen_outb(unsigned char b, unsigned long addr)
{
- if (__is_local(addr))
- __local_outb(b, addr);
+ if (jensen_is_local(addr))
+ jensen_local_outb(b, addr);
else
- _bus_outb(b, addr);
+ jensen_bus_outb(b, addr);
}
-extern inline unsigned int __inw(unsigned long addr)
+__EXTERN_INLINE unsigned int jensen_inw(unsigned long addr)
{
long result;
- __set_hae(0);
+ jensen_set_hae(0);
result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
result >>= (addr & 3) * 8;
return 0xffffUL & result;
}
-extern inline unsigned int __inl(unsigned long addr)
+__EXTERN_INLINE unsigned int jensen_inl(unsigned long addr)
{
- __set_hae(0);
- return *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60);
+ jensen_set_hae(0);
+ return *(vuip) ((addr << 7) + EISA_IO + 0x60);
}
-extern inline void __outw(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void jensen_outw(unsigned short b, unsigned long addr)
{
- __set_hae(0);
- *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
+ jensen_set_hae(0);
+ *(vuip) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
mb();
}
-extern inline void __outl(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void jensen_outl(unsigned int b, unsigned long addr)
{
- __set_hae(0);
- *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60) = b;
+ jensen_set_hae(0);
+ *(vuip) ((addr << 7) + EISA_IO + 0x60) = b;
mb();
}
/*
* Memory functions.
*/
-extern inline unsigned long __readb(unsigned long addr)
+
+__EXTERN_INLINE unsigned long jensen_readb(unsigned long addr)
{
long result;
- __set_hae(addr);
- addr &= __HAE_MASK;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
result >>= (addr & 3) * 8;
return 0xffUL & result;
}
-extern inline unsigned long __readw(unsigned long addr)
+__EXTERN_INLINE unsigned long jensen_readw(unsigned long addr)
{
long result;
- __set_hae(addr);
- addr &= __HAE_MASK;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
result >>= (addr & 3) * 8;
return 0xffffUL & result;
}
-extern inline unsigned long __readl(unsigned long addr)
+__EXTERN_INLINE unsigned long jensen_readl(unsigned long addr)
{
- __set_hae(addr);
- addr &= __HAE_MASK;
- return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60);
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
+ return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
}
-extern inline unsigned long __readq(unsigned long addr)
+__EXTERN_INLINE unsigned long jensen_readq(unsigned long addr)
{
unsigned long r0, r1;
- __set_hae(addr);
- addr &= __HAE_MASK;
+
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
addr = (addr << 7) + EISA_MEM + 0x60;
- r0 = *(volatile unsigned int *) (addr);
- r1 = *(volatile unsigned int *) (addr + (4 << 7));
+ r0 = *(vuip) (addr);
+ r1 = *(vuip) (addr + (4 << 7));
return r1 << 32 | r0;
}
-extern inline void __writeb(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeb(unsigned char b, unsigned long addr)
{
- __set_hae(addr);
- addr &= __HAE_MASK;
- *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
+ *(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
}
-extern inline void __writew(unsigned short b, unsigned long addr)
+__EXTERN_INLINE void jensen_writew(unsigned short b, unsigned long addr)
{
- __set_hae(addr);
- addr &= __HAE_MASK;
- *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
+ *(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
}
-extern inline void __writel(unsigned int b, unsigned long addr)
+__EXTERN_INLINE void jensen_writel(unsigned int b, unsigned long addr)
{
- __set_hae(addr);
- addr &= __HAE_MASK;
- *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
+ *(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
}
-extern inline void __writeq(unsigned long b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeq(unsigned long b, unsigned long addr)
{
- __set_hae(addr);
- addr &= __HAE_MASK;
+ jensen_set_hae(addr);
+ addr &= JENSEN_HAE_MASK;
addr = (addr << 7) + EISA_MEM + 0x60;
- *(volatile unsigned int *) (addr) = b;
- *(volatile unsigned int *) (addr + (4 << 7)) = b >> 32;
+ *(vuip) (addr) = b;
+ *(vuip) (addr + (4 << 7)) = b >> 32;
+}
+
+/* Find the DENSE memory area for a given bus address.
+ Whee, there is none. */
+
+__EXTERN_INLINE unsigned long jensen_dense_mem(unsigned long addr)
+{
+ return 0;
}
+#undef vuip
+
+#ifdef __WANT_IO_DEF
+
+#define virt_to_bus jensen_virt_to_bus
+#define bus_to_virt jensen_bus_to_virt
+#define __inb jensen_inb
+#define __inw jensen_inw
+#define __inl jensen_inl
+#define __outb jensen_outb
+#define __outw jensen_outw
+#define __outl jensen_outl
+#define __readb jensen_readb
+#define __readw jensen_readw
+#define __writeb jensen_writeb
+#define __writew jensen_writew
+#define __readl jensen_readl
+#define __readq jensen_readq
+#define __writel jensen_writel
+#define __writeq jensen_writeq
+#define dense_mem jensen_dense_mem
+
/*
* The above have so much overhead that it probably doesn't make
* sense to have them inlined (better icache behaviour).
#define outb(x, port) \
(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
-#endif /* __KERNEL__ */
-
-/*
- * The Alpha Jensen hardware for some rather strange reason puts
- * the RTC clock at 0x170 instead of 0x70. Probably due to some
- * misguided idea about using 0x70 for NMI stuff.
- *
- * These defines will override the defaults when doing RTC queries
- */
-#define RTC_PORT(x) (0x170+(x))
-#define RTC_ADDR(x) (x)
-#define RTC_ALWAYS_BCD 0
+#endif /* __WANT_IO_DEF */
+#ifdef __IO_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __IO_EXTERN_INLINE
#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_JENSEN_H */
+++ /dev/null
-#ifndef __ALPHA_LCA__H__
-#define __ALPHA_LCA__H__
-
-/*
- * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
- * for example).
- *
- * This file is based on:
- *
- * DECchip 21066 and DECchip 21068 Alpha AXP Microprocessors
- * Hardware Reference Manual; Digital Equipment Corp.; May 1994;
- * Maynard, MA; Order Number: EC-N2681-71.
- */
-
-/*
- * NOTE: The LCA uses a Host Address Extension (HAE) register to access
- * PCI addresses that are beyond the first 27 bits of address
- * space. Updating the HAE requires an external cycle (and
- * a memory barrier), which tends to be slow. Instead of updating
- * it on each sparse memory access, we keep the current HAE value
- * cached in variable cache_hae. Only if the cached HAE differs
- * from the desired HAE value do we actually updated HAE register.
- * The HAE register is preserved by the interrupt handler entry/exit
- * code, so this scheme works even in the presence of interrupts.
- *
- * Dense memory space doesn't require the HAE, but is restricted to
- * aligned 32 and 64 bit accesses. Special Cycle and Interrupt
- * Acknowledge cycles may also require the use of the HAE. The LCA
- * limits I/O address space to the bottom 24 bits of address space,
- * but this easily covers the 16 bit ISA I/O address space.
- */
-
-/*
- * NOTE 2! The memory operations do not set any memory barriers, as
- * it's not needed for cases like a frame buffer that is essentially
- * memory-like. You need to do them by hand if the operations depend
- * on ordering.
- *
- * Similarly, the port I/O operations do a "mb" only after a write
- * operation: if an mb is needed before (as in the case of doing
- * memory mapped I/O first, and then a port I/O operation to the same
- * device), it needs to be done by hand.
- *
- * After the above has bitten me 100 times, I'll give up and just do
- * the mb all the time, but right now I'm hoping this will work out.
- * Avoiding mb's may potentially be a noticeable speed improvement,
- * but I can't honestly say I've tested it.
- *
- * Handling interrupts that need to do mb's to synchronize to
- * non-interrupts is another fun race area. Don't do it (because if
- * you do, I'll have to do *everything* with interrupts disabled,
- * ugh).
- */
-
-#include <linux/config.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define LCA_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define LCA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int LCA_DMA_WIN_BASE;
-extern unsigned int LCA_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define LCA_DMA_WIN_BASE (1024*1024*1024)
-#define LCA_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-/*
- * Memory Controller registers:
- */
-#define LCA_MEM_BCR0 (IDENT_ADDR + 0x120000000UL)
-#define LCA_MEM_BCR1 (IDENT_ADDR + 0x120000008UL)
-#define LCA_MEM_BCR2 (IDENT_ADDR + 0x120000010UL)
-#define LCA_MEM_BCR3 (IDENT_ADDR + 0x120000018UL)
-#define LCA_MEM_BMR0 (IDENT_ADDR + 0x120000020UL)
-#define LCA_MEM_BMR1 (IDENT_ADDR + 0x120000028UL)
-#define LCA_MEM_BMR2 (IDENT_ADDR + 0x120000030UL)
-#define LCA_MEM_BMR3 (IDENT_ADDR + 0x120000038UL)
-#define LCA_MEM_BTR0 (IDENT_ADDR + 0x120000040UL)
-#define LCA_MEM_BTR1 (IDENT_ADDR + 0x120000048UL)
-#define LCA_MEM_BTR2 (IDENT_ADDR + 0x120000050UL)
-#define LCA_MEM_BTR3 (IDENT_ADDR + 0x120000058UL)
-#define LCA_MEM_GTR (IDENT_ADDR + 0x120000060UL)
-#define LCA_MEM_ESR (IDENT_ADDR + 0x120000068UL)
-#define LCA_MEM_EAR (IDENT_ADDR + 0x120000070UL)
-#define LCA_MEM_CAR (IDENT_ADDR + 0x120000078UL)
-#define LCA_MEM_VGR (IDENT_ADDR + 0x120000080UL)
-#define LCA_MEM_PLM (IDENT_ADDR + 0x120000088UL)
-#define LCA_MEM_FOR (IDENT_ADDR + 0x120000090UL)
-
-/*
- * I/O Controller registers:
- */
-#define LCA_IOC_HAE (IDENT_ADDR + 0x180000000UL)
-#define LCA_IOC_CONF (IDENT_ADDR + 0x180000020UL)
-#define LCA_IOC_STAT0 (IDENT_ADDR + 0x180000040UL)
-#define LCA_IOC_STAT1 (IDENT_ADDR + 0x180000060UL)
-#define LCA_IOC_TBIA (IDENT_ADDR + 0x180000080UL)
-#define LCA_IOC_TB_ENA (IDENT_ADDR + 0x1800000a0UL)
-#define LCA_IOC_SFT_RST (IDENT_ADDR + 0x1800000c0UL)
-#define LCA_IOC_PAR_DIS (IDENT_ADDR + 0x1800000e0UL)
-#define LCA_IOC_W_BASE0 (IDENT_ADDR + 0x180000100UL)
-#define LCA_IOC_W_BASE1 (IDENT_ADDR + 0x180000120UL)
-#define LCA_IOC_W_MASK0 (IDENT_ADDR + 0x180000140UL)
-#define LCA_IOC_W_MASK1 (IDENT_ADDR + 0x180000160UL)
-#define LCA_IOC_T_BASE0 (IDENT_ADDR + 0x180000180UL)
-#define LCA_IOC_T_BASE1 (IDENT_ADDR + 0x1800001a0UL)
-#define LCA_IOC_TB_TAG0 (IDENT_ADDR + 0x188000000UL)
-#define LCA_IOC_TB_TAG1 (IDENT_ADDR + 0x188000020UL)
-#define LCA_IOC_TB_TAG2 (IDENT_ADDR + 0x188000040UL)
-#define LCA_IOC_TB_TAG3 (IDENT_ADDR + 0x188000060UL)
-#define LCA_IOC_TB_TAG4 (IDENT_ADDR + 0x188000070UL)
-#define LCA_IOC_TB_TAG5 (IDENT_ADDR + 0x1880000a0UL)
-#define LCA_IOC_TB_TAG6 (IDENT_ADDR + 0x1880000c0UL)
-#define LCA_IOC_TB_TAG7 (IDENT_ADDR + 0x1880000e0UL)
-
-/*
- * Memory spaces:
- */
-#define LCA_IACK_SC (IDENT_ADDR + 0x1a0000000UL)
-#define LCA_CONF (IDENT_ADDR + 0x1e0000000UL)
-#define LCA_IO (IDENT_ADDR + 0x1c0000000UL)
-#define LCA_SPARSE_MEM (IDENT_ADDR + 0x200000000UL)
-#define LCA_DENSE_MEM (IDENT_ADDR + 0x300000000UL)
-#define DENSE_MEM(addr) LCA_DENSE_MEM
-
-/*
- * Bit definitions for I/O Controller status register 0:
- */
-#define LCA_IOC_STAT0_CMD 0xf
-#define LCA_IOC_STAT0_ERR (1<<4)
-#define LCA_IOC_STAT0_LOST (1<<5)
-#define LCA_IOC_STAT0_THIT (1<<6)
-#define LCA_IOC_STAT0_TREF (1<<7)
-#define LCA_IOC_STAT0_CODE_SHIFT 8
-#define LCA_IOC_STAT0_CODE_MASK 0x7
-#define LCA_IOC_STAT0_P_NBR_SHIFT 13
-#define LCA_IOC_STAT0_P_NBR_MASK 0x7ffff
-
-#define HAE_ADDRESS LCA_IOC_HAE
-
-/* LCA PMR Power Management register defines */
-#define LCA_PMR_ADDR (IDENT_ADDR + 0x120000098UL)
-#define LCA_PMR_PDIV 0x7 /* Primary clock divisor */
-#define LCA_PMR_ODIV 0x38 /* Override clock divisor */
-#define LCA_PMR_INTO 0x40 /* Interrupt override */
-#define LCA_PMR_DMAO 0x80 /* DMA override */
-#define LCA_PMR_OCCEB 0xffff0000L /* Override cycle counter - even
- bits */
-#define LCA_PMR_OCCOB 0xffff000000000000L /* Override cycle counter - even
- bits */
-#define LCA_PMR_PRIMARY_MASK 0xfffffffffffffff8
-/* LCA PMR Macros */
-
-#define READ_PMR (*(volatile unsigned long *)LCA_PMR_ADDR)
-#define WRITE_PMR(d) (*((volatile unsigned long *)LCA_PMR_ADDR) = (d))
-
-#define GET_PRIMARY(r) ((r) & LCA_PMR_PDIV)
-#define GET_OVERRIDE(r) (((r) >> 3) & LCA_PMR_PDIV)
-#define SET_PRIMARY_CLOCK(r, c) ((r) = (((r) & LCA_PMR_PRIMARY_MASK) | (c)))
-
-/* LCA PMR Divisor values */
-#define DIV_1 0x0
-#define DIV_1_5 0x1
-#define DIV_2 0x2
-#define DIV_4 0x3
-#define DIV_8 0x4
-#define DIV_16 0x5
-#define DIV_MIN DIV_1
-#define DIV_MAX DIV_16
-
-
-#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) + LCA_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- /*
- * This check is a sanity check but also ensures that bus
- * address 0 maps to virtual address 0 which is useful to
- * detect null "pointers" (the NCR driver is much simpler if
- * NULL pointers are preserved).
- */
- if (address < LCA_DMA_WIN_BASE)
- return 0;
- return phys_to_virt(address - LCA_DMA_WIN_BASE);
-}
-
-/*
- * I/O functions:
- *
- * Unlike Jensen, the Noname machines have no concept of local
- * I/O---everything goes over the PCI bus.
- *
- * There is plenty room for optimization here. In particular,
- * the Alpha's insb/insw/extb/extw should be useful in moving
- * data to/from the right byte-lanes.
- */
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + LCA_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + LCA_IO + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + LCA_IO + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + LCA_IO + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip) ((addr << 5) + LCA_IO + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip) ((addr << 5) + LCA_IO + 0x18) = b;
- mb();
-}
-
-
-/*
- * Memory functions. 64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, msb;
-
- shift = (addr & 0x3) * 8;
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- result = *(vuip) ((addr << 5) + LCA_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;
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- result = *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08);
- result >>= shift;
- return 0xffffUL & result;
-}
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip) (addr + LCA_DENSE_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp) (addr + LCA_DENSE_MEM);
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long msb;
- unsigned int w;
-
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
- *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long msb;
- unsigned int w;
-
- if (addr >= (1UL << 24)) {
- msb = addr & 0xf8000000;
- addr -= msb;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- }
- asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
- *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip) (addr + LCA_DENSE_MEM) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp) (addr + LCA_DENSE_MEM) = b;
-}
-
-/*
- * Most of the above have so much overhead that it probably doesn't
- * make sense to have them inlined (better icache behavior).
- */
-
-#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 readq(a) __readq((unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vuip
-#undef vulp
-
-extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling LCA machine checks. Correctable errors
- * result in a short logout frame, uncorrectable ones in a long one.
- */
-struct el_lca_mcheck_short {
- struct el_common h; /* common logout header */
- unsigned long esr; /* error-status register */
- unsigned long ear; /* error-address register */
- unsigned long dc_stat; /* dcache status register */
- unsigned long ioc_stat0; /* I/O controller status register 0 */
- unsigned long ioc_stat1; /* I/O controller status register 1 */
-};
-
-struct el_lca_mcheck_long {
- struct el_common h; /* common logout header */
- unsigned long pt[31]; /* PAL temps */
- unsigned long exc_addr; /* exception address */
- unsigned long pad1[3];
- unsigned long pal_base; /* PALcode base address */
- unsigned long hier; /* hw interrupt enable */
- unsigned long hirr; /* hw interrupt request */
- unsigned long mm_csr; /* MMU control & status */
- unsigned long dc_stat; /* data cache status */
- unsigned long dc_addr; /* data cache addr register */
- unsigned long abox_ctl; /* address box control register */
- unsigned long esr; /* error status register */
- unsigned long ear; /* error address register */
- unsigned long car; /* cache control register */
- unsigned long ioc_stat0; /* I/O controller status register 0 */
- unsigned long ioc_stat1; /* I/O controller status register 1 */
- unsigned long va; /* virtual address register */
-};
-
-union el_lca {
- struct el_common * c;
- struct el_lca_mcheck_long * l;
- struct el_lca_mcheck_short * s;
-};
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_LCA__H__ */
--- /dev/null
+#ifndef __ALPHA_MACHVEC_H
+#define __ALPHA_MACHVEC_H 1
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+
+/* The following structure vectors all of the I/O and IRQ manipulation
+ from the generic kernel to the hardware specific backend. */
+
+struct task_struct;
+struct mm_struct;
+struct pt_regs;
+struct vm_area_struct;
+
+struct alpha_machine_vector
+{
+ /* This "belongs" down below with the rest of the runtime
+ variables, but it is convenient for entry.S if these
+ two slots are at the beginning of the struct. */
+ unsigned long hae_cache;
+ unsigned long *hae_register;
+
+ unsigned long max_dma_address;
+ unsigned int nr_irqs;
+ unsigned int rtc_port, rtc_addr;
+ unsigned int max_asn;
+ unsigned long mmu_context_mask;
+ unsigned long irq_probe_mask;
+ unsigned long iack_sc;
+
+ unsigned long (*mv_virt_to_bus)(void *);
+ void * (*mv_bus_to_virt)(unsigned long);
+
+ unsigned int (*mv_inb)(unsigned long);
+ unsigned int (*mv_inw)(unsigned long);
+ unsigned int (*mv_inl)(unsigned long);
+
+ void (*mv_outb)(unsigned char, unsigned long);
+ void (*mv_outw)(unsigned short, unsigned long);
+ void (*mv_outl)(unsigned int, unsigned long);
+
+ unsigned long (*mv_readb)(unsigned long);
+ unsigned long (*mv_readw)(unsigned long);
+ unsigned long (*mv_readl)(unsigned long);
+ unsigned long (*mv_readq)(unsigned long);
+
+ void (*mv_writeb)(unsigned char, unsigned long);
+ void (*mv_writew)(unsigned short, unsigned long);
+ void (*mv_writel)(unsigned int, unsigned long);
+ void (*mv_writeq)(unsigned long, unsigned long);
+
+ unsigned long (*mv_dense_mem)(unsigned long);
+
+ int (*pci_read_config_byte)(u8, u8, u8, u8 *value);
+ int (*pci_read_config_word)(u8, u8, u8, u16 *value);
+ int (*pci_read_config_dword)(u8, u8, u8, u32 *value);
+
+ int (*pci_write_config_byte)(u8, u8, u8, u8 value);
+ int (*pci_write_config_word)(u8, u8, u8, u16 value);
+ int (*pci_write_config_dword)(u8, u8, u8, u32 value);
+
+ void (*mv_get_mmu_context)(struct task_struct *);
+ void (*mv_flush_tlb_current)(struct mm_struct *);
+ void (*mv_flush_tlb_other)(struct mm_struct *);
+ void (*mv_flush_tlb_current_page)(struct mm_struct * mm,
+ struct vm_area_struct *vma,
+ unsigned long addr);
+
+ void (*update_irq_hw)(unsigned long, unsigned long, int);
+ void (*ack_irq)(unsigned long);
+ void (*device_interrupt)(unsigned long vector, struct pt_regs *regs);
+ void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs);
+
+ void (*init_arch)(unsigned long *, unsigned long *);
+ void (*init_irq)(void);
+ void (*init_pit)(void);
+ void (*pci_fixup)(void);
+ void (*kill_arch)(int, char *);
+
+ const char *vector_name;
+
+ /* System specific parameters. */
+ union {
+ struct {
+ unsigned long gru_int_req_bits;
+ } cia;
+
+ struct {
+ unsigned long gamma_bias;
+ } t2;
+ } sys;
+
+ /* Runtime variables it is handy to keep close. */
+ unsigned long dma_win_base;
+ unsigned long dma_win_size;
+ unsigned long sm_base_r1, sm_base_r2, sm_base_r3;
+};
+
+extern struct alpha_machine_vector alpha_mv;
+
+#ifdef CONFIG_ALPHA_GENERIC
+extern int alpha_using_srm;
+extern int alpha_use_srm_setup;
+#else
+#ifdef CONFIG_ALPHA_SRM
+#define alpha_using_srm 1
+#else
+#define alpha_using_srm 0
+#endif
+#if defined(CONFIG_ALPHA_SRM_SETUP)
+#define alpha_use_srm_setup 1
+#else
+#define alpha_use_srm_setup 0
+#endif
+#endif /* GENERIC */
+
+#endif /* __ALPHA_MACHVEC_H */
+++ /dev/null
-#ifndef __ALPHA_MCPCIA__H__
-#define __ALPHA_MCPCIA__H__
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-/*
- * MCPCIA is the internal name for a core logic chipset which provides
- * PCI access for the RAWHIDE family of systems.
- *
- * This file is based on:
- *
- * RAWHIDE System Programmer's Manual
- * 16-May-96
- * Rev. 1.4
- *
- */
-
-/*------------------------------------------------------------------------**
-** **
-** 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 **
-** **
-**------------------------------------------------------------------------*/
-
-
-/* MCPCIA 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_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
-#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
-#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define MCPCIA_DMA_WIN_BASE_DEFAULT (2*1024*1024*1024U)
-#define MCPCIA_DMA_WIN_SIZE_DEFAULT (2*1024*1024*1024U)
-
-extern unsigned int MCPCIA_DMA_WIN_BASE;
-extern unsigned int MCPCIA_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define MCPCIA_DMA_WIN_BASE (2*1024*1024*1024UL)
-#define MCPCIA_DMA_WIN_SIZE (2*1024*1024*1024UL)
-#endif /* SRM_SETUP */
-
-#define HOSE(h) (((unsigned long)(h)) << 33)
-/*
- * General Registers
- */
-#define MCPCIA_REV(h) (IDENT_ADDR + 0xf9e0000000UL + HOSE(h))
-#define MCPCIA_WHOAMI(h) (IDENT_ADDR + 0xf9e0000040UL + HOSE(h))
-#define MCPCIA_PCI_LAT(h) (IDENT_ADDR + 0xf9e0000080UL + HOSE(h))
-#define MCPCIA_CAP_CTRL(h) (IDENT_ADDR + 0xf9e0000100UL + HOSE(h))
-#define MCPCIA_HAE_MEM(h) (IDENT_ADDR + 0xf9e0000400UL + HOSE(h))
-#define MCPCIA_HAE_IO(h) (IDENT_ADDR + 0xf9e0000440UL + HOSE(h))
-#if 0
-#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9e0000480UL + HOSE(h))
-#endif
-#define MCPCIA_HAE_DENSE(h) (IDENT_ADDR + 0xf9e00004c0UL + HOSE(h))
-
-/*
- * Interrupt Control registers
- */
-#define MCPCIA_INT_CTL(h) (IDENT_ADDR + 0xf9e0000500UL + HOSE(h))
-#define MCPCIA_INT_REQ(h) (IDENT_ADDR + 0xf9e0000540UL + HOSE(h))
-#define MCPCIA_INT_TARG(h) (IDENT_ADDR + 0xf9e0000580UL + HOSE(h))
-#define MCPCIA_INT_ADR(h) (IDENT_ADDR + 0xf9e00005c0UL + HOSE(h))
-#define MCPCIA_INT_ADR_EXT(h) (IDENT_ADDR + 0xf9e0000600UL + HOSE(h))
-#define MCPCIA_INT_MASK0(h) (IDENT_ADDR + 0xf9e0000640UL + HOSE(h))
-#define MCPCIA_INT_MASK1(h) (IDENT_ADDR + 0xf9e0000680UL + HOSE(h))
-#define MCPCIA_INT_ACK0(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
-#define MCPCIA_INT_ACK1(h) (IDENT_ADDR + 0xf9e0003f40UL + HOSE(h))
-
-/*
- * Performance Monitor registers
- */
-#define MCPCIA_PERF_MONITOR(h) (IDENT_ADDR + 0xf9e0000300UL + HOSE(h))
-#define MCPCIA_PERF_CONTROL(h) (IDENT_ADDR + 0xf9e0000340UL + HOSE(h))
-
-/*
- * Diagnostic Registers
- */
-#define MCPCIA_CAP_DIAG(h) (IDENT_ADDR + 0xf9e0000700UL + HOSE(h))
-#define MCPCIA_TOP_OF_MEM(h) (IDENT_ADDR + 0xf9e00007c0UL + HOSE(h))
-
-/*
- * Error registers
- */
-#define MCPCIA_CAP_ERR(h) (IDENT_ADDR + 0xf9e0000880UL + HOSE(h))
-#define MCPCIA_PCI_ERR1(h) (IDENT_ADDR + 0xf9e0001040UL + HOSE(h))
-
-/*
- * PCI Address Translation Registers.
- */
-#define MCPCIA_SG_TBIA(h) (IDENT_ADDR + 0xf9e0001300UL + HOSE(h))
-#define MCPCIA_HBASE(h) (IDENT_ADDR + 0xf9e0001340UL + HOSE(h))
-
-#define MCPCIA_W0_BASE(h) (IDENT_ADDR + 0xf9e0001400UL + HOSE(h))
-#define MCPCIA_W0_MASK(h) (IDENT_ADDR + 0xf9e0001440UL + HOSE(h))
-#define MCPCIA_T0_BASE(h) (IDENT_ADDR + 0xf9e0001480UL + HOSE(h))
-
-#define MCPCIA_W1_BASE(h) (IDENT_ADDR + 0xf9e0001500UL + HOSE(h))
-#define MCPCIA_W1_MASK(h) (IDENT_ADDR + 0xf9e0001540UL + HOSE(h))
-#define MCPCIA_T1_BASE(h) (IDENT_ADDR + 0xf9e0001580UL + HOSE(h))
-
-#define MCPCIA_W2_BASE(h) (IDENT_ADDR + 0xf9e0001600UL + HOSE(h))
-#define MCPCIA_W2_MASK(h) (IDENT_ADDR + 0xf9e0001640UL + HOSE(h))
-#define MCPCIA_T2_BASE(h) (IDENT_ADDR + 0xf9e0001680UL + HOSE(h))
-
-#define MCPCIA_W3_BASE(h) (IDENT_ADDR + 0xf9e0001700UL + HOSE(h))
-#define MCPCIA_W3_MASK(h) (IDENT_ADDR + 0xf9e0001740UL + HOSE(h))
-#define MCPCIA_T3_BASE(h) (IDENT_ADDR + 0xf9e0001780UL + HOSE(h))
-
-/*
- * Memory spaces:
- */
-#define MCPCIA_CONF(h) (IDENT_ADDR + 0xf9c0000000UL + HOSE(h))
-#define MCPCIA_IO(h) (IDENT_ADDR + 0xf980000000UL + HOSE(h))
-#define MCPCIA_SPARSE(h) (IDENT_ADDR + 0xf800000000UL + HOSE(h))
-#define MCPCIA_DENSE(h) (IDENT_ADDR + 0xf900000000UL + HOSE(h))
-#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
-
-#define DENSE_MEM(addr) MCPCIA_DENSE(((unsigned long)(addr) >> 32) & 3)
-
-#define HAE_ADDRESS MCPCIA_HAE_MEM(0)
-
-#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) + MCPCIA_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address - MCPCIA_DMA_WIN_BASE);
-}
-
-/*
- * I/O functions:
- *
- * MCPCIA, the RAWHIDE family PCI/memory support chipset for the EV5 (21164)
- * and EV56 (21164a) processors, can use either a sparse address mapping
- * scheme, or the so-called byte-word PCI address space, to get at PCI memory
- * and I/O.
- *
- * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE.
- */
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-#ifdef DISABLE_BWIO_ENABLED
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO)));
-
- return result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO)), "r" (b));
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO)));
-
- return result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO)), "r" (b));
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldl %0,%1"
- : "=r" (result)
- : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO)));
-
- return result;
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stl %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO)), "r" (b));
-}
-
-#define inb(port) __inb((port))
-#define inw(port) __inw((port))
-#define inl(port) __inl((port))
-
-#define outb(x, port) __outb((x),(port))
-#define outw(x, port) __outw((x),(port))
-#define outl(x, port) __outl((x),(port))
-
-#else /* BWIO_ENABLED */
-
-extern inline unsigned int __inb(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- long result = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- long result = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- return *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18) = b;
- mb();
-}
-
-#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)))
-
-#endif /* BWIO_ENABLED */
-
-
-/*
- * 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
- *
- */
-
-#ifdef DISABLE_BWIO_ENABLED
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM)));
-
- return result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM)));
-
- return result;
-}
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip)(addr + MCPCIA_BW_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp)(addr + MCPCIA_BW_MEM);
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM))
- : "r" (b));
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM))
- : "r" (b));
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip)(addr+MCPCIA_BW_MEM) = b;
- mb();
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp)(addr+MCPCIA_BW_MEM) = b;
- mb();
-}
-
-#define readb(addr) __readb((addr))
-#define readw(addr) __readw((addr))
-
-#define writeb(b, addr) __writeb((b),(addr))
-#define writew(b, addr) __writew((b),(addr))
-
-#else /* BWIO_ENABLED */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-
-extern unsigned long mcpcia_sm_base_r1, mcpcia_sm_base_r2, mcpcia_sm_base_r3;
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= mcpcia_sm_base_r1) &&
- (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r2) &&
- (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r3) &&
- (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__readb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffUL & result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= mcpcia_sm_base_r1) &&
- (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x08);
- else
- if ((addr >= mcpcia_sm_base_r2) &&
- (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x08);
- else
- if ((addr >= mcpcia_sm_base_r3) &&
- (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x08);
- else
- {
-#if 0
- printk("__readw: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= mcpcia_sm_base_r1) &&
- (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r2) &&
- (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r3) &&
- (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writeb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= mcpcia_sm_base_r1) &&
- (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r2) &&
- (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= mcpcia_sm_base_r3) &&
- (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writew: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x00010001;
-}
-
-#else /* SRM_SETUP */
-
-extern inline unsigned long __readb(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned long result, shift, msb, work, temp;
-
- shift = (addr & 0x3) << 3;
- msb = addr & 0xE0000000UL;
- temp = addr & MEM_R1_MASK;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00);
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffUL & result;
-}
-
-extern inline unsigned long __readw(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned long result, shift, msb, work, temp;
-
- shift = (addr & 0x3) << 3;
- msb = addr & 0xE0000000UL;
- temp = addr & MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08);
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned long msb;
-
- msb = addr & 0xE0000000;
- addr &= MEM_R1_MASK;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001;
-}
-#endif /* SRM_SETUP */
-
-extern inline unsigned long __readl(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- return *(vuip) (addr + MCPCIA_DENSE(hose));
-}
-
-extern inline unsigned long __readq(unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- return *(vulp) (addr + MCPCIA_DENSE(hose));
-}
-
-extern inline void __writel(unsigned int b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- *(vuip) (addr + MCPCIA_DENSE(hose)) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long in_addr)
-{
- unsigned long addr = in_addr & 0xffffffffUL;
- unsigned long hose = (in_addr >> 32) & 3;
- *(vulp) (addr + MCPCIA_DENSE(hose)) = b;
-}
-
-#endif /* BWIO_ENABLED */
-
-#define readl(a) __readl((unsigned long)(a))
-#define readq(a) __readq((unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vuip
-#undef vulp
-
-struct linux_hose_info {
- struct pci_bus pci_bus;
- struct linux_hose_info *next;
- unsigned long pci_io_space;
- unsigned long pci_mem_space;
- unsigned long pci_config_space;
- unsigned long pci_sparse_space;
- unsigned int pci_first_busno;
- unsigned int pci_last_busno;
- unsigned int pci_hose_index;
-};
-
-extern unsigned long mcpcia_init (unsigned long, unsigned long);
-extern void mcpcia_fixup (void);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling MCPCIA machine checks:
- */
-struct el_MCPCIA_uncorrected_frame_mcheck {
- struct el_common header;
- struct el_common_EV5_uncorrectable_mcheck procdata;
-};
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_MCPCIA__H__ */
#include <linux/config.h>
#include <asm/system.h>
+#include <asm/machvec.h>
/*
* The maximum ASN's the processor supports. On the EV4 this is 63
* work correctly and can thus not be used (explaining the lack of PAL-code
* support).
*/
-#ifdef CONFIG_ALPHA_EV5
-#define MAX_ASN 127
+#define EV4_MAX_ASN 63
+#define EV5_MAX_ASN 127
+
+#ifdef CONFIG_ALPHA_GENERIC
+# define MAX_ASN (alpha_mv.max_asn)
#else
-#define MAX_ASN 63
-#define BROKEN_ASN 1
+# ifdef CONFIG_ALPHA_EV4
+# define MAX_ASN EV4_MAX_ASN
+# else
+# define MAX_ASN EV5_MAX_ASN
+# endif
#endif
#ifdef __SMP__
* force a new asn for any other processes the next time they want to
* run.
*/
-extern inline void
-get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __MMU_EXTERN_INLINE
+#endif
+
+extern void get_new_mmu_context(struct task_struct *p, struct mm_struct *mm);
+
+__EXTERN_INLINE void ev4_get_mmu_context(struct task_struct *p)
{
- unsigned long asn = asn_cache;
-
- if ((asn & HARDWARE_ASN_MASK) < MAX_ASN)
- ++asn;
- else {
- tbiap();
- imb();
- asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
- }
- asn_cache = asn;
- mm->context = asn; /* full version + asn */
- p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */
+ /* As described, ASN's are broken. */
}
-extern inline void get_mmu_context(struct task_struct *p)
+__EXTERN_INLINE void ev5_get_mmu_context(struct task_struct *p)
{
-#ifndef BROKEN_ASN
struct mm_struct * mm = p->mm;
if (mm) {
if ((mm->context ^ asn) & ~HARDWARE_ASN_MASK)
get_new_mmu_context(p, mm);
}
-#endif
}
+#ifdef CONFIG_ALPHA_GENERIC
+# define get_mmu_context (alpha_mv.mv_get_mmu_context)
+#else
+# ifdef CONFIG_ALPHA_EV4
+# define get_mmu_context ev4_get_mmu_context
+# else
+# define get_mmu_context ev5_get_mmu_context
+# endif
+#endif
+
extern inline void init_new_context(struct mm_struct *mm)
{
mm->context = 0;
}
-#define destroy_context(mm) do { } while(0)
+extern inline void destroy_context(struct mm_struct *mm)
+{
+ /* Nothing to do. */
+}
+
/*
- * After we have set current->mm to a new value, this activates
- * the context for the new mm so we see the new mappings.
- * Ideally this would be an extern inline function, but reload_context
- * is declared in pgtable.h, which includes this file. :-(
+ * Force a context reload. This is needed when we change the page
+ * table pointer or when we update the ASN of the current process.
*/
-#define activate_context(tsk) \
- do { \
- get_mmu_context(tsk); \
- reload_context(tsk); \
- } while (0)
+#if defined(CONFIG_ALPHA_GENERIC)
+#define MASK_CONTEXT(tss) \
+ ((struct thread_struct *)((unsigned long)(tss) & alpha_mv.mmu_context_mask))
+#elif defined(CONFIG_ALPHA_DP264)
+#define MASK_CONTEXT(tss) \
+ ((struct thread_struct *)((unsigned long)(tss) & 0xfffffffffful))
+#else
+#define MASK_CONTEXT(tss) (tss)
+#endif
+
+__EXTERN_INLINE struct thread_struct *
+__reload_tss(struct thread_struct *tss)
+{
+ register struct thread_struct *a0 __asm__("$16");
+ register struct thread_struct *v0 __asm__("$0");
+
+ a0 = MASK_CONTEXT(tss);
+
+ __asm__ __volatile__(
+ "call_pal %2" : "=r"(v0), "=r"(a0)
+ : "i"(PAL_swpctx), "r"(a0)
+ : "$1", "$16", "$22", "$23", "$24", "$25");
+
+ return v0;
+}
+
+__EXTERN_INLINE void
+reload_context(struct task_struct *task)
+{
+ __reload_tss(&task->tss);
+}
+
+/*
+ * After we have set current->mm to a new value, this activates the
+ * context for the new mm so we see the new mappings.
+ */
+
+__EXTERN_INLINE void
+activate_context(struct task_struct *task)
+{
+ get_mmu_context(task);
+ reload_context(task);
+}
+
+#ifdef __MMU_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __MMU_EXTERN_INLINE
#endif
+#endif /* __ALPHA_MMU_CONTEXT_H */
--- /dev/null
+#ifndef __ALPHA_PCI_H
+#define __ALPHA_PCI_H
+
+#include <linux/config.h>
+#include <linux/pci.h>
+
+
+/*
+ * The following structure is used to manage multiple PCI busses.
+ *
+ * XXX: We should solve thos problem in an architecture independant
+ * way, rather than hacking something up here.
+ */
+
+struct linux_hose_info {
+ struct pci_bus pci_bus;
+ struct linux_hose_info *next;
+ unsigned long pci_io_space;
+ unsigned long pci_mem_space;
+ unsigned long pci_config_space;
+ unsigned long pci_sparse_space;
+ unsigned int pci_first_busno;
+ unsigned int pci_last_busno;
+ unsigned int pci_hose_index;
+};
+
+/* This is indexed by a pseudo- PCI bus number to obtain the real deal. */
+extern struct linux_hose_info *bus2hose[256];
+
+/* Create a handle that is OR-ed into the reported I/O space address
+ for a device. We use this later to find the bus a device lives on. */
+
+#if defined(CONFIG_ALPHA_GENERIC) \
+ || defined(CONFIG_ALPHA_MCPCIA) \
+ /* || defined(CONFIG_ALPHA_TSUNAMI) */
+
+#define PCI_HANDLE(bus) ((bus2hose[bus]->pci_hose_index & 3UL) << 32)
+#define DEV_IS_ON_PRIMARY(dev) \
+ (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
+
+#else
+
+#define PCI_HANDLE(bus) 0
+#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0)
+
+#endif /* Multiple busses */
+
+#endif /* __ALPHA_PCI_H */
#include <asm/system.h>
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/mmu_context.h>
+#include <asm/machvec.h>
+
/* Caches aren't brain-dead on the Alpha. */
#define flush_cache_all() do { } while (0)
#define flush_page_to_ram(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
-/*
- * Force a context reload. This is needed when we
- * change the page table pointer or when we update
- * the ASN of the current process.
- */
-static inline void reload_context(struct task_struct *task)
-{
- __asm__ __volatile__(
-#ifdef CONFIG_ALPHA_DP264
- "zap %0,0xe0,$16\n\t"
-#else
- "bis %0,%0,$16\n\t"
-#endif
- "call_pal %1"
- : /* no outputs */
- : "r" (&task->tss), "i" (PAL_swpctx)
- : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
-}
-
/*
* Use a few helper functions to hide the ugly broken ASN
* numbers on early Alphas (ev4 and ev45)
*/
-#ifdef BROKEN_ASN
-#define flush_tlb_current(x) tbiap()
-#define flush_tlb_other(x) do { } while (0)
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __MMU_EXTERN_INLINE
+#endif
-#else
+__EXTERN_INLINE void
+ev4_flush_tlb_current(struct mm_struct *mm)
+{
+ tbiap();
+}
-extern void get_new_asn_and_reload(struct task_struct *, struct mm_struct *);
+__EXTERN_INLINE void
+ev4_flush_tlb_other(struct mm_struct *mm)
+{
+}
-#define flush_tlb_current(mm) get_new_asn_and_reload(current, mm)
-#define flush_tlb_other(mm) do { (mm)->context = 0; } while (0)
+__EXTERN_INLINE void
+ev5_flush_tlb_current(struct mm_struct *mm)
+{
+ mm->context = 0;
+ get_new_mmu_context(current, mm);
+ reload_context(current);
+}
-#endif
+__EXTERN_INLINE void
+ev5_flush_tlb_other(struct mm_struct *mm)
+{
+ mm->context = 0;
+}
/*
* Flush just one page in the current TLB set.
* We need to be very careful about the icache here, there
* is no way to invalidate a specific icache page..
*/
-static inline void flush_tlb_current_page(struct mm_struct * mm,
- struct vm_area_struct *vma,
- unsigned long addr)
+
+__EXTERN_INLINE void
+ev4_flush_tlb_current_page(struct mm_struct * mm,
+ struct vm_area_struct *vma,
+ unsigned long addr)
{
-#ifdef BROKEN_ASN
tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
-#else
+}
+
+__EXTERN_INLINE void
+ev5_flush_tlb_current_page(struct mm_struct * mm,
+ struct vm_area_struct *vma,
+ unsigned long addr)
+{
if (vma->vm_flags & VM_EXEC)
- flush_tlb_current(mm);
+ ev5_flush_tlb_current(mm);
else
tbi(2, addr);
-#endif
}
+
+#ifdef CONFIG_ALPHA_GENERIC
+# define flush_tlb_current alpha_mv.mv_flush_tlb_current
+# define flush_tlb_other alpha_mv.mv_flush_tlb_other
+# define flush_tlb_current_page alpha_mv.mv_flush_tlb_current_page
+#else
+# ifdef CONFIG_ALPHA_EV4
+# define flush_tlb_current ev4_flush_tlb_current
+# define flush_tlb_other ev4_flush_tlb_other
+# define flush_tlb_current_page ev4_flush_tlb_current_page
+# else
+# define flush_tlb_current ev5_flush_tlb_current
+# define flush_tlb_other ev5_flush_tlb_other
+# define flush_tlb_current_page ev5_flush_tlb_current_page
+# endif
+#endif
+
+#ifdef __MMU_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __MMU_EXTERN_INLINE
+#endif
+
/*
* Flush current user mapping.
*/
int val[2];
} __kernel_fsid_t;
+#ifdef __KERNEL__
+
#ifndef __GNUC__
#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
#endif /* __GNUC__ */
+#endif /* __KERNEL__ */
+
#endif /* _ALPHA_POSIX_TYPES_H */
* holds provided the thread blocked through a call to schedule() ($15
* is the frame pointer in schedule() and $15 is saved at offset 48 by
* entry.S:do_switch_stack).
+ *
+ * Under heavy swap load I've seen this loose in an ugly way. So do
+ * some extra sanity checking on the ranges we expect these pointers
+ * to be in so that we can fail gracefully. This is just for ps after
+ * all. -- r~
*/
extern inline unsigned long thread_saved_pc(struct thread_struct *t)
{
- unsigned long fp;
-
- fp = ((unsigned long*)t->ksp)[6];
- return *(unsigned long*)fp;
+ unsigned long fp, sp = t->ksp, base = (unsigned long)t;
+
+ if (sp > base && sp+6*8 < base + 16*1024) {
+ fp = ((unsigned long*)sp)[6];
+ if (fp > sp && fp < base + 16*1024)
+ return *(unsigned long *)fp;
+ }
+
+ return 0;
}
/*
+++ /dev/null
-#ifndef __ALPHA_PYXIS__H__
-#define __ALPHA_PYXIS__H__
-
-#include <linux/config.h>
-#include <linux/types.h>
-
-/*
- * PYXIS is the internal name for a core logic chipset which provides
- * memory controller and PCI access for the 21164A chip based systems.
- *
- * This file is based on:
- *
- * Pyxis Chipset Spec
- * 14-Jun-96
- * Rev. X2.0
- *
- */
-
-/*------------------------------------------------------------------------**
-** **
-** 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 **
-** **
-**------------------------------------------------------------------------*/
-
-
-/* CIA 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_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */
-#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */
-#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int PYXIS_DMA_WIN_BASE;
-extern unsigned int PYXIS_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define PYXIS_DMA_WIN_BASE (1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-/*
- * General Registers
- */
-#define PYXIS_REV (IDENT_ADDR + 0x8740000080UL)
-#define PYXIS_PCI_LAT (IDENT_ADDR + 0x87400000C0UL)
-#define PYXIS_CTRL (IDENT_ADDR + 0x8740000100UL)
-#define PYXIS_CTRL1 (IDENT_ADDR + 0x8740000140UL)
-#define PYXIS_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL)
-
-#define PYXIS_HAE_MEM (IDENT_ADDR + 0x8740000400UL)
-#define PYXIS_HAE_IO (IDENT_ADDR + 0x8740000440UL)
-#define PYXIS_CFG (IDENT_ADDR + 0x8740000480UL)
-
-/*
- * Diagnostic Registers
- */
-#define PYXIS_DIAG (IDENT_ADDR + 0x8740002000UL)
-#define PYXIS_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL)
-
-/*
- * Performance Monitor registers
- */
-#define PYXIS_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL)
-#define PYXIS_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL)
-
-/*
- * Error registers
- */
-#define PYXIS_ERR (IDENT_ADDR + 0x8740008200UL)
-#define PYXIS_STAT (IDENT_ADDR + 0x8740008240UL)
-#define PYXIS_ERR_MASK (IDENT_ADDR + 0x8740008280UL)
-#define PYXIS_SYN (IDENT_ADDR + 0x8740008300UL)
-#define PYXIS_ERR_DATA (IDENT_ADDR + 0x8740008308UL)
-
-#define PYXIS_MEAR (IDENT_ADDR + 0x8740008400UL)
-#define PYXIS_MESR (IDENT_ADDR + 0x8740008440UL)
-#define PYXIS_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL)
-#define PYXIS_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL)
-#define PYXIS_PCI_ERR2 (IDENT_ADDR + 0x8740008880UL)
-
-/*
- * PCI Address Translation Registers.
- */
-#define PYXIS_TBIA (IDENT_ADDR + 0x8760000100UL)
-
-#define PYXIS_W0_BASE (IDENT_ADDR + 0x8760000400UL)
-#define PYXIS_W0_MASK (IDENT_ADDR + 0x8760000440UL)
-#define PYXIS_T0_BASE (IDENT_ADDR + 0x8760000480UL)
-
-#define PYXIS_W1_BASE (IDENT_ADDR + 0x8760000500UL)
-#define PYXIS_W1_MASK (IDENT_ADDR + 0x8760000540UL)
-#define PYXIS_T1_BASE (IDENT_ADDR + 0x8760000580UL)
-
-#define PYXIS_W2_BASE (IDENT_ADDR + 0x8760000600UL)
-#define PYXIS_W2_MASK (IDENT_ADDR + 0x8760000640UL)
-#define PYXIS_T2_BASE (IDENT_ADDR + 0x8760000680UL)
-
-#define PYXIS_W3_BASE (IDENT_ADDR + 0x8760000700UL)
-#define PYXIS_W3_MASK (IDENT_ADDR + 0x8760000740UL)
-#define PYXIS_T3_BASE (IDENT_ADDR + 0x8760000780UL)
-
-/*
- * Memory Control registers
- */
-#define PYXIS_MCR (IDENT_ADDR + 0x8750000000UL)
-
-/*
- * Memory spaces:
- */
-#define PYXIS_IACK_SC (IDENT_ADDR + 0x8720000000UL)
-#define PYXIS_CONF (IDENT_ADDR + 0x8700000000UL)
-#define PYXIS_IO (IDENT_ADDR + 0x8580000000UL)
-#define PYXIS_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL)
-#define PYXIS_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL)
-#define PYXIS_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL)
-#define PYXIS_DENSE_MEM (IDENT_ADDR + 0x8600000000UL)
-#define DENSE_MEM(addr) PYXIS_DENSE_MEM
-
-/*
- * Byte/Word PCI Memory Spaces:
- */
-#define PYXIS_BW_MEM (IDENT_ADDR + 0x8800000000UL)
-#define PYXIS_BW_IO (IDENT_ADDR + 0x8900000000UL)
-#define PYXIS_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL)
-#define PYXIS_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL)
-
-/*
- * Interrupt Control registers
- */
-#define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL)
-#define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL)
-#define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL)
-#define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL)
-#define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL)
-#define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL)
-#define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL)
-#define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL)
-#define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL)
-
-/*
- * Bit definitions for I/O Controller status register 0:
- */
-#define PYXIS_STAT0_CMD 0xf
-#define PYXIS_STAT0_ERR (1<<4)
-#define PYXIS_STAT0_LOST (1<<5)
-#define PYXIS_STAT0_THIT (1<<6)
-#define PYXIS_STAT0_TREF (1<<7)
-#define PYXIS_STAT0_CODE_SHIFT 8
-#define PYXIS_STAT0_CODE_MASK 0x7
-#define PYXIS_STAT0_P_NBR_SHIFT 13
-#define PYXIS_STAT0_P_NBR_MASK 0x7ffff
-
-#define HAE_ADDRESS PYXIS_HAE_MEM
-
-#ifdef __KERNEL__
-
-/*
- * Translate physical memory address as seen on (PCI) bus into
- * a kernel virtual address and vv.
- */
-#if defined(CONFIG_ALPHA_RUFFIAN)
-/* Ruffian doesn't do 1G PCI window */
-
-extern inline unsigned long virt_to_bus(void * address)
-{
- return virt_to_phys(address);
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address);
-}
-#else /* RUFFIAN */
-extern inline unsigned long virt_to_bus(void * address)
-{
- return virt_to_phys(address) + PYXIS_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address - PYXIS_DMA_WIN_BASE);
-}
-#endif /* RUFFIAN */
-
-/*
- * I/O functions:
- *
- * PYXIS, the 21174 PCI/memory support chipset for the EV56 (21164A)
- * and PCA56 (21164PC) processors, can use either a sparse address
- * mapping scheme, or the so-called byte-word PCI address space, to
- * get at PCI memory and I/O.
- */
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-#ifdef BWIO_ENABLED
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO)));
-
- return result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO))
- : "r" (b));
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO)));
-
- return result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO))
- : "r" (b));
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip)(addr+PYXIS_BW_IO);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip)(addr+PYXIS_BW_IO) = b;
- mb();
-}
-
-#define inb(port) __inb((port))
-#define inw(port) __inw((port))
-#define inl(port) __inl((port))
-
-#define outb(x, port) __outb((x),(port))
-#define outw(x, port) __outw((x),(port))
-#define outl(x, port) __outl((x),(port))
-
-#else /* BWIO_ENABLED */
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + PYXIS_IO + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + PYXIS_IO + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip) ((addr << 5) + PYXIS_IO + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip) ((addr << 5) + PYXIS_IO + 0x18) = b;
- mb();
-}
-
-#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)))
-
-#endif /* BWIO_ENABLED */
-
-
-/*
- * 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
- *
- */
-
-#ifdef BWIO_ENABLED
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM)));
-
- return result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- register unsigned long result;
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM)));
-
- return result;
-}
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip)(addr+PYXIS_BW_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp)(addr+PYXIS_BW_MEM);
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM))
- : "r" (b));
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM))
- : "r" (b));
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip)(addr+PYXIS_BW_MEM) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp)(addr+PYXIS_BW_MEM) = b;
-}
-
-#define readb(addr) __readb((addr))
-#define readw(addr) __readw((addr))
-
-#define writeb(b, addr) __writeb((b),(addr))
-#define writew(b, addr) __writew((b),(addr))
-
-#else /* BWIO_ENABLED */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-
-extern unsigned long pyxis_sm_base_r1, pyxis_sm_base_r2, pyxis_sm_base_r3;
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= pyxis_sm_base_r1) &&
- (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00);
- else
- if ((addr >= pyxis_sm_base_r2) &&
- (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= pyxis_sm_base_r3) &&
- (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__readb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffUL & result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if ((addr >= pyxis_sm_base_r1) &&
- (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x08);
- else
- if ((addr >= pyxis_sm_base_r2) &&
- (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x08);
- else
- if ((addr >= pyxis_sm_base_r3) &&
- (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x08);
- else
- {
-#if 0
- printk("__readw: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0x0ffffUL;
- }
- shift = (addr & 0x3) << 3;
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= pyxis_sm_base_r1) &&
- (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00);
- else
- if ((addr >= pyxis_sm_base_r2) &&
- (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= pyxis_sm_base_r3) &&
- (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writeb: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long work;
-
- if ((addr >= pyxis_sm_base_r1) &&
- (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK)))
- work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00);
- else
- if ((addr >= pyxis_sm_base_r2) &&
- (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK)))
- work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00);
- else
- if ((addr >= pyxis_sm_base_r3) &&
- (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK)))
- work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00);
- else
- {
-#if 0
- printk("__writew: address 0x%lx not covered by HAE\n", addr);
-#endif
- return;
- }
- *(vuip) work = b * 0x00010001;
-}
-
-#else /* SRM_SETUP */
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, msb, work, temp;
-
- shift = (addr & 0x3) << 3;
- msb = addr & 0xE0000000UL;
- temp = addr & MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00);
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffUL & result;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- unsigned long result, shift, msb, work, temp;
-
- shift = (addr & 0x3) << 3;
- msb = addr & 0xE0000000UL;
- temp = addr & MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08);
- result = *(vuip) work;
- result >>= shift;
- return 0x0ffffUL & result;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001;
-}
-#endif /* SRM_SETUP */
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip) (addr + PYXIS_DENSE_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp) (addr + PYXIS_DENSE_MEM);
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip) (addr + PYXIS_DENSE_MEM) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp) (addr + PYXIS_DENSE_MEM) = b;
-}
-
-#endif /* BWIO_ENABLED */
-
-#define readl(a) __readl((unsigned long)(a))
-#define readq(a) __readq((unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vuip
-#undef vulp
-
-extern unsigned long pyxis_init (unsigned long mem_start,
- unsigned long mem_end);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling PYXIS machine checks:
- */
-struct el_PYXIS_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_PYXIS__H__ */
? __constant_c_memset((s),0x0001000100010001UL*(unsigned short)(c),(n)) \
: __memsetw((s),(c),(n)))
+extern int strcasecmp(const char *, const char *);
+
#endif /* __KERNEL__ */
#endif /* __ALPHA_STRING_H__ */
#define switch_to(prev,next) do { \
current = next; \
- alpha_switch_to((unsigned long) ¤t->tss - 0xfffffc0000000000); \
+ alpha_switch_to((unsigned long) ¤t->tss - IDENT_ADDR); \
} while (0)
extern void alpha_switch_to(unsigned long pctxp);
#define mb() \
__asm__ __volatile__("mb": : :"memory")
+#define wmb() \
+__asm__ __volatile__("wmb": : :"memory")
+
#define imb() \
__asm__ __volatile__ ("call_pal %0" : : "i" (PAL_imb) : "memory")
+++ /dev/null
-#ifndef __ALPHA_T2__H__
-#define __ALPHA_T2__H__
-
-#include <linux/config.h>
-#include <linux/types.h>
-
-/*
- * T2 is the internal name for the core logic chipset which provides
- * memory controller and PCI access for the SABLE-based systems.
- *
- * This file is based on:
- *
- * SABLE I/O Specification
- * Revision/Update Information: 1.3
- *
- * jestabro@amt.tay1.dec.com Initial Version.
- *
- */
-
-#define BYTE_ENABLE_SHIFT 5
-#define TRANSFER_LENGTH_SHIFT 3
-#define MEM_R1_MASK 0x03ffffff /* Mem sparse space region 1 mask is 26 bits */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define T2_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define T2_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int T2_DMA_WIN_BASE;
-extern unsigned int T2_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define T2_DMA_WIN_BASE (1024*1024*1024)
-#define T2_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-/* GAMMA-SABLE is a SABLE with EV5-based CPUs */
-#ifdef CONFIG_ALPHA_GAMMA
-# define GAMMA_BIAS 0x8000000000UL
-#else /* GAMMA */
-# define GAMMA_BIAS 0x0000000000UL
-#endif /* GAMMA */
-
-/*
- * Memory spaces:
- */
-#define T2_CONF (IDENT_ADDR + GAMMA_BIAS + 0x390000000UL)
-#define T2_IO (IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL)
-#define T2_SPARSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x200000000UL)
-#define T2_DENSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL)
-#define DENSE_MEM(addr) T2_DENSE_MEM
-
-#define T2_IOCSR (IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL)
-#define T2_CERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL)
-#define T2_CERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000040UL)
-#define T2_CERR3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000060UL)
-#define T2_PERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000080UL)
-#define T2_PERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000a0UL)
-#define T2_PSCR (IDENT_ADDR + GAMMA_BIAS + 0x38e0000c0UL)
-#define T2_HAE_1 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000e0UL)
-#define T2_HAE_2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000100UL)
-#define T2_HBASE (IDENT_ADDR + GAMMA_BIAS + 0x38e000120UL)
-#define T2_WBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000140UL)
-#define T2_WMASK1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000160UL)
-#define T2_TBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000180UL)
-#define T2_WBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001a0UL)
-#define T2_WMASK2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001c0UL)
-#define T2_TBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001e0UL)
-#define T2_TLBBR (IDENT_ADDR + GAMMA_BIAS + 0x38e000200UL)
-
-#define T2_HAE_3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000240UL)
-#define T2_HAE_4 (IDENT_ADDR + GAMMA_BIAS + 0x38e000260UL)
-
-#define HAE_ADDRESS T2_HAE_1
-
-/* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to
- 3.8fff.ffff
- *
- * +--------------+ 3 8000 0000
- * | CPU 0 CSRs |
- * +--------------+ 3 8100 0000
- * | CPU 1 CSRs |
- * +--------------+ 3 8200 0000
- * | CPU 2 CSRs |
- * +--------------+ 3 8300 0000
- * | CPU 3 CSRs |
- * +--------------+ 3 8400 0000
- * | CPU Reserved |
- * +--------------+ 3 8700 0000
- * | Mem Reserved |
- * +--------------+ 3 8800 0000
- * | Mem 0 CSRs |
- * +--------------+ 3 8900 0000
- * | Mem 1 CSRs |
- * +--------------+ 3 8a00 0000
- * | Mem 2 CSRs |
- * +--------------+ 3 8b00 0000
- * | Mem 3 CSRs |
- * +--------------+ 3 8c00 0000
- * | Mem Reserved |
- * +--------------+ 3 8e00 0000
- * | PCI Bridge |
- * +--------------+ 3 8f00 0000
- * | Expansion IO |
- * +--------------+ 3 9000 0000
- *
- *
- */
-#define CPU0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x380000000L)
-#define CPU1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x381000000L)
-#define CPU2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x382000000L)
-#define CPU3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x383000000L)
-#define MEM0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x388000000L)
-#define MEM1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x389000000L)
-#define MEM2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38a000000L)
-#define MEM3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38b000000L)
-
-#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) + T2_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address - T2_DMA_WIN_BASE);
-}
-
-/*
- * I/O functions:
- *
- * T2 (the core logic PCI/memory support chipset for the SABLE
- * 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) + T2_IO + 0x00);
- result >>= (addr & 3) * 8;
- return 0xffUL & result;
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_insbl(b, addr & 3);
- *(vuip) ((addr << 5) + T2_IO + 0x00) = w;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- long result = *(vuip) ((addr << 5) + T2_IO + 0x08);
- result >>= (addr & 3) * 8;
- return 0xffffUL & result;
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- unsigned int w;
-
- w = __kernel_inswl(b, addr & 3);
- *(vuip) ((addr << 5) + T2_IO + 0x08) = w;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip) ((addr << 5) + T2_IO + 0x18);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip) ((addr << 5) + T2_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
- *
- */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-
-extern unsigned long t2_sm_base;
-
-extern int __t2_ioaddr_check(unsigned long addr)
-{
- if ((addr >= t2_sm_base && addr <= t2_sm_base + MEM_R1_MASK)
- || (addr >= 512*1024 && addr < 1024*1024))
- return 1;
-#if 0
- printk("T2: address 0x%lx not covered by HAE\n", addr);
-#endif
- return 0;
-}
-
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if (!__t2_addr_check(addr))
- return 0xFF;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
- result = *(vuip) work;
- shift = (addr & 0x3) << 3;
- return (result >> shift) & 0xFF;
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- unsigned long result, shift, work;
-
- if (!__t2_addr_check(addr))
- return 0xFFFF;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
- result = *(vuip) work;
- shift = (addr & 0x3) << 3;
- return (result >> shift) & 0xFF;
-}
-
-/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
-extern inline unsigned long __readl(unsigned long addr)
-{
- unsigned long work;
-
- if (!__t2_addr_check(addr))
- return 0xFFFFFFFF;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
- return *(vuip) work;
-}
-
-/* ... which makes me wonder why we advertise we have DENSE memory at all.
- Anyway, guess that means we should emulate 64-bit access as two cycles. */
-extern inline unsigned long __readq(unsigned long addr)
-{
- unsigned long work, r0, r1;
-
- if (!__t2_addr_check(addr))
- return ~0UL;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
- r0 = *(vuip) work0;
- r1 = *(vuip) (work0 + (4 << 5));
- return r1 << 32 | r0;
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long work;
-
- if (!__t2_addr_check(addr))
- return;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00);
- *(vuip) work = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long work;
-
- if (!__t2_addr_check(addr))
- return;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08);
- *(vuip) work = b * 0x00010001;
-}
-
-/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- unsigned long work;
-
- if (!__t2_addr_check(addr))
- return;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
- *(vuip) work = b;
-}
-
-/* ... which makes me wonder why we advertise we have DENSE memory at all.
- Anyway, guess that means we should emulate 64-bit access as two cycles. */
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- unsigned long work;
-
- if (!__t2_addr_check(addr))
- return;
-
- work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18);
- *(vuip) work0 = b;
- *(vuip) (work0 + (4 << 5)) = (b >> 32);
-}
-
-#else /* SRM_SETUP */
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- unsigned long result, shift, msb;
-
- shift = (addr & 0x3) * 8 ;
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- result = *(vuip) ((addr << 5) + T2_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_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
- result >>= shift;
- return 0xffffUL & result;
-}
-
-/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */
-extern inline unsigned long __readl(unsigned long addr)
-{
- unsigned long result, msb;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
- return 0xffffffffUL & result;
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- unsigned long r0, r1, work, msb;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = (addr << 5) + T2_SPARSE_MEM + 0x18;
- r0 = *(vuip)(work);
- r1 = *(vuip)(work + (4 << 5));
- return r1 << 32 | r0;
-}
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101;
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = b * 0x00010001;
-}
-
-/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- unsigned long msb ;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- unsigned long msb, work;
-
- msb = addr & 0xE0000000 ;
- addr &= MEM_R1_MASK ;
- if (msb != hae.cache) {
- set_hae(msb);
- }
- work = (addr << 5) + T2_SPARSE_MEM + 0x18;
- *(vuip)work = b;
- *(vuip)(work + (4 << 5)) = b >> 32;
-}
-
-#endif /* SRM_SETUP */
-
-#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)))
-
-#undef vuip
-
-extern unsigned long t2_init (unsigned long mem_start,
- unsigned long mem_end);
-
-#endif /* __KERNEL__ */
-
-/*
- * Sable CPU Module CSRS
- *
- * These are CSRs for hardware other than the CPU chip on the CPU module.
- * The CPU module has Backup Cache control logic, Cbus control logic, and
- * interrupt control logic on it. There is a duplicate tag store to speed
- * up maintaining cache coherency.
- */
-
-struct sable_cpu_csr {
-unsigned long bcc; long fill_00[3]; /* Backup Cache Control */
-unsigned long bcce; long fill_01[3]; /* Backup Cache Correctable Error */
-unsigned long bccea; long fill_02[3]; /* B-Cache Corr Err Address Latch */
-unsigned long bcue; long fill_03[3]; /* B-Cache Uncorrectable Error */
-unsigned long bcuea; long fill_04[3]; /* B-Cache Uncorr Err Addr Latch */
-unsigned long dter; long fill_05[3]; /* Duplicate Tag Error */
-unsigned long cbctl; long fill_06[3]; /* CBus Control */
-unsigned long cbe; long fill_07[3]; /* CBus Error */
-unsigned long cbeal; long fill_08[3]; /* CBus Error Addr Latch low */
-unsigned long cbeah; long fill_09[3]; /* CBus Error Addr Latch high */
-unsigned long pmbx; long fill_10[3]; /* Processor Mailbox */
-unsigned long ipir; long fill_11[3]; /* Inter-Processor Int Request */
-unsigned long sic; long fill_12[3]; /* System Interrupt Clear */
-unsigned long adlk; long fill_13[3]; /* Address Lock (LDxL/STxC) */
-unsigned long madrl; long fill_14[3]; /* CBus Miss Address */
-unsigned long rev; long fill_15[3]; /* CMIC Revision */
-};
-
-/*
- * Data structure for handling T2 machine checks:
- */
-struct el_t2_frame_header {
- unsigned int elcf_fid; /* Frame ID (from above) */
- unsigned int elcf_size; /* Size of frame in bytes */
-};
-
-struct el_t2_procdata_mcheck {
- unsigned long elfmc_paltemp[32]; /* PAL TEMP REGS. */
- /* EV4-specific fields */
- unsigned long elfmc_exc_addr; /* Addr of excepting insn. */
- unsigned long elfmc_exc_sum; /* Summary of arith traps. */
- unsigned long elfmc_exc_mask; /* Exception mask (from exc_sum). */
- unsigned long elfmc_iccsr; /* IBox hardware enables. */
- unsigned long elfmc_pal_base; /* Base address for PALcode. */
- unsigned long elfmc_hier; /* Hardware Interrupt Enable. */
- unsigned long elfmc_hirr; /* Hardware Interrupt Request. */
- unsigned long elfmc_mm_csr; /* D-stream fault info. */
- unsigned long elfmc_dc_stat; /* D-cache status (ECC/Parity Err). */
- unsigned long elfmc_dc_addr; /* EV3 Phys Addr for ECC/DPERR. */
- unsigned long elfmc_abox_ctl; /* ABox Control Register. */
- unsigned long elfmc_biu_stat; /* BIU Status. */
- unsigned long elfmc_biu_addr; /* BUI Address. */
- unsigned long elfmc_biu_ctl; /* BIU Control. */
- unsigned long elfmc_fill_syndrome; /* For correcting ECC errors. */
- unsigned long elfmc_fill_addr;/* Cache block which was being read. */
- unsigned long elfmc_va; /* Effective VA of fault or miss. */
- unsigned long elfmc_bc_tag; /* Backup Cache Tag Probe Results. */
-};
-
-/*
- * Sable processor specific Machine Check Data segment.
- */
-
-struct el_t2_logout_header {
- unsigned int elfl_size; /* size in bytes of logout area. */
- int elfl_sbz1:31; /* Should be zero. */
- char elfl_retry:1; /* Retry flag. */
- unsigned int elfl_procoffset; /* Processor-specific offset. */
- unsigned int elfl_sysoffset; /* Offset of system-specific. */
- unsigned int elfl_error_type; /* PAL error type code. */
- unsigned int elfl_frame_rev; /* PAL Frame revision. */
-};
-struct el_t2_sysdata_mcheck {
- unsigned long elcmc_bcc; /* CSR 0 */
- unsigned long elcmc_bcce; /* CSR 1 */
- unsigned long elcmc_bccea; /* CSR 2 */
- unsigned long elcmc_bcue; /* CSR 3 */
- unsigned long elcmc_bcuea; /* CSR 4 */
- unsigned long elcmc_dter; /* CSR 5 */
- unsigned long elcmc_cbctl; /* CSR 6 */
- unsigned long elcmc_cbe; /* CSR 7 */
- unsigned long elcmc_cbeal; /* CSR 8 */
- unsigned long elcmc_cbeah; /* CSR 9 */
- unsigned long elcmc_pmbx; /* CSR 10 */
- unsigned long elcmc_ipir; /* CSR 11 */
- unsigned long elcmc_sic; /* CSR 12 */
- unsigned long elcmc_adlk; /* CSR 13 */
- unsigned long elcmc_madrl; /* CSR 14 */
- unsigned long elcmc_crrev4; /* CSR 15 */
-};
-
-/*
- * Sable memory error frame - sable pfms section 3.42
- */
-struct el_t2_data_memory {
- struct el_t2_frame_header elcm_hdr; /* ID$MEM-FERR = 0x08 */
- unsigned int elcm_module; /* Module id. */
- unsigned int elcm_res04; /* Reserved. */
- unsigned long elcm_merr; /* CSR0: Error Reg 1. */
- unsigned long elcm_mcmd1; /* CSR1: Command Trap 1. */
- unsigned long elcm_mcmd2; /* CSR2: Command Trap 2. */
- unsigned long elcm_mconf; /* CSR3: Configuration. */
- unsigned long elcm_medc1; /* CSR4: EDC Status 1. */
- unsigned long elcm_medc2; /* CSR5: EDC Status 2. */
- unsigned long elcm_medcc; /* CSR6: EDC Control. */
- unsigned long elcm_msctl; /* CSR7: Stream Buffer Control. */
- unsigned long elcm_mref; /* CSR8: Refresh Control. */
- unsigned long elcm_filter; /* CSR9: CRD Filter Control. */
-};
-
-
-/*
- * Sable other CPU error frame - sable pfms section 3.43
- */
-struct el_t2_data_other_cpu {
- short elco_cpuid; /* CPU ID */
- short elco_res02[3];
- unsigned long elco_bcc; /* CSR 0 */
- unsigned long elco_bcce; /* CSR 1 */
- unsigned long elco_bccea; /* CSR 2 */
- unsigned long elco_bcue; /* CSR 3 */
- unsigned long elco_bcuea; /* CSR 4 */
- unsigned long elco_dter; /* CSR 5 */
- unsigned long elco_cbctl; /* CSR 6 */
- unsigned long elco_cbe; /* CSR 7 */
- unsigned long elco_cbeal; /* CSR 8 */
- unsigned long elco_cbeah; /* CSR 9 */
- unsigned long elco_pmbx; /* CSR 10 */
- unsigned long elco_ipir; /* CSR 11 */
- unsigned long elco_sic; /* CSR 12 */
- unsigned long elco_adlk; /* CSR 13 */
- unsigned long elco_madrl; /* CSR 14 */
- unsigned long elco_crrev4; /* CSR 15 */
-};
-
-/*
- * Sable other CPU error frame - sable pfms section 3.44
- */
-struct el_t2_data_t2{
- struct el_t2_frame_header elct_hdr; /* ID$T2-FRAME */
- unsigned long elct_iocsr; /* IO Control and Status Register */
- unsigned long elct_cerr1; /* Cbus Error Register 1 */
- unsigned long elct_cerr2; /* Cbus Error Register 2 */
- unsigned long elct_cerr3; /* Cbus Error Register 3 */
- unsigned long elct_perr1; /* PCI Error Register 1 */
- unsigned long elct_perr2; /* PCI Error Register 2 */
- unsigned long elct_hae0_1; /* High Address Extension Register 1 */
- unsigned long elct_hae0_2; /* High Address Extension Register 2 */
- unsigned long elct_hbase; /* High Base Register */
- unsigned long elct_wbase1; /* Window Base Register 1 */
- unsigned long elct_wmask1; /* Window Mask Register 1 */
- unsigned long elct_tbase1; /* Translated Base Register 1 */
- unsigned long elct_wbase2; /* Window Base Register 2 */
- unsigned long elct_wmask2; /* Window Mask Register 2 */
- unsigned long elct_tbase2; /* Translated Base Register 2 */
- unsigned long elct_tdr0; /* TLB Data Register 0 */
- unsigned long elct_tdr1; /* TLB Data Register 1 */
- unsigned long elct_tdr2; /* TLB Data Register 2 */
- unsigned long elct_tdr3; /* TLB Data Register 3 */
- unsigned long elct_tdr4; /* TLB Data Register 4 */
- unsigned long elct_tdr5; /* TLB Data Register 5 */
- unsigned long elct_tdr6; /* TLB Data Register 6 */
- unsigned long elct_tdr7; /* TLB Data Register 7 */
-};
-
-/*
- * Sable error log data structure - sable pfms section 3.40
- */
-struct el_t2_data_corrected {
- unsigned long elcpb_biu_stat;
- unsigned long elcpb_biu_addr;
- unsigned long elcpb_biu_ctl;
- unsigned long elcpb_fill_syndrome;
- unsigned long elcpb_fill_addr;
- unsigned long elcpb_bc_tag;
-};
-
-/*
- * Sable error log data structure
- * Note there are 4 memory slots on sable (see t2.h)
- */
-struct el_t2_frame_mcheck {
- struct el_t2_frame_header elfmc_header; /* ID$P-FRAME_MCHECK */
- struct el_t2_logout_header elfmc_hdr;
- struct el_t2_procdata_mcheck elfmc_procdata;
- struct el_t2_sysdata_mcheck elfmc_sysdata;
- struct el_t2_data_t2 elfmc_t2data;
- struct el_t2_data_memory elfmc_memdata[4];
- struct el_t2_frame_header elfmc_footer; /* empty */
-};
-
-
-/*
- * Sable error log data structures on memory errors
- */
-struct el_t2_frame_corrected {
- struct el_t2_frame_header elfcc_header; /* ID$P-BC-COR */
- struct el_t2_logout_header elfcc_hdr;
- struct el_t2_data_corrected elfcc_procdata;
-/* struct el_t2_data_t2 elfcc_t2data; */
-/* struct el_t2_data_memory elfcc_memdata[4]; */
- struct el_t2_frame_header elfcc_footer; /* empty */
-};
-
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_T2__H__ */
+++ /dev/null
-#ifndef __ALPHA_TSUNAMI__H__
-#define __ALPHA_TSUNAMI__H__
-
-#include <linux/config.h>
-#include <linux/types.h>
-
-/*
- * TSUNAMI/TYPHOON are the internal names for the core logic chipset which
- * provides memory controller and PCI access for the 21264 based systems.
- *
- * This file is based on:
- *
- * Tsunami System Programmers Manual
- * Preliminary, Chapters 2-5
- *
- */
-
-#define BYTE_ENABLE_SHIFT 5
-#define TRANSFER_LENGTH_SHIFT 3
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* if we are using the SRM PCI setup, we'll need to use variables instead */
-#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024)
-#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024)
-
-extern unsigned int TSUNAMI_DMA_WIN_BASE;
-extern unsigned int TSUNAMI_DMA_WIN_SIZE;
-
-#else /* SRM_SETUP */
-#define TSUNAMI_DMA_WIN_BASE (1024*1024*1024)
-#define TSUNAMI_DMA_WIN_SIZE (1024*1024*1024)
-#endif /* SRM_SETUP */
-
-#ifdef USE_48_BIT_KSEG
-#define TS_BIAS 0x80000000000UL
-#else
-#define TS_BIAS 0x10000000000UL
-#endif
-
-/*
- * CChip and DChip registers
- */
-#define TSUNAMI_CSR_CSC (IDENT_ADDR + TS_BIAS + 0x1A0000000UL)
-#define TSUNAMI_CSR_MTR (IDENT_ADDR + TS_BIAS + 0x1A0000040UL)
-#define TSUNAMI_CSR_MISC (IDENT_ADDR + TS_BIAS + 0x1A0000080UL)
-#define TSUNAMI_CSR_MPD (IDENT_ADDR + TS_BIAS + 0x1A00000C0UL)
-#define TSUNAMI_CSR_AAR0 (IDENT_ADDR + TS_BIAS + 0x1A0000100UL)
-#define TSUNAMI_CSR_AAR1 (IDENT_ADDR + TS_BIAS + 0x1A0000140UL)
-#define TSUNAMI_CSR_AAR2 (IDENT_ADDR + TS_BIAS + 0x1A0000180UL)
-#define TSUNAMI_CSR_AAR3 (IDENT_ADDR + TS_BIAS + 0x1A00001C0UL)
-#define TSUNAMI_CSR_DIM0 (IDENT_ADDR + TS_BIAS + 0x1A0000200UL)
-#define TSUNAMI_CSR_DIM1 (IDENT_ADDR + TS_BIAS + 0x1A0000240UL)
-#define TSUNAMI_CSR_DIR0 (IDENT_ADDR + TS_BIAS + 0x1A0000280UL)
-#define TSUNAMI_CSR_DIR1 (IDENT_ADDR + TS_BIAS + 0x1A00002C0UL)
-
-#define TSUNAMI_CSR_DRIR (IDENT_ADDR + TS_BIAS + 0x1A0000300UL)
-#define TSUNAMI_CSR_PRBEN (IDENT_ADDR + TS_BIAS + 0x1A0000340UL)
-#define TSUNAMI_CSR_IIC (IDENT_ADDR + TS_BIAS + 0x1A0000380UL)
-#define TSUNAMI_CSR_WDR (IDENT_ADDR + TS_BIAS + 0x1A00003C0UL)
-#define TSUNAMI_CSR_MPR0 (IDENT_ADDR + TS_BIAS + 0x1A0000400UL)
-#define TSUNAMI_CSR_MPR1 (IDENT_ADDR + TS_BIAS + 0x1A0000440UL)
-#define TSUNAMI_CSR_MPR2 (IDENT_ADDR + TS_BIAS + 0x1A0000480UL)
-#define TSUNAMI_CSR_MPR3 (IDENT_ADDR + TS_BIAS + 0x1A00004C0UL)
-#define TSUNAMI_CSR_TTR (IDENT_ADDR + TS_BIAS + 0x1A0000580UL)
-#define TSUNAMI_CSR_TDR (IDENT_ADDR + TS_BIAS + 0x1A00005C0UL)
-#define TSUNAMI_CSR_DSC (IDENT_ADDR + TS_BIAS + 0x1B0000800UL)
-#define TSUNAMI_CSR_STR (IDENT_ADDR + TS_BIAS + 0x1B0000840UL)
-#define TSUNAMI_CSR_DREV (IDENT_ADDR + TS_BIAS + 0x1B0000880UL)
-
-/*
- * PChip registers
- */
-#define TSUNAMI_PCHIP0_WSBA0 (IDENT_ADDR + TS_BIAS + 0x180000000UL)
-#define TSUNAMI_PCHIP0_WSBA1 (IDENT_ADDR + TS_BIAS + 0x180000040UL)
-#define TSUNAMI_PCHIP0_WSBA2 (IDENT_ADDR + TS_BIAS + 0x180000080UL)
-#define TSUNAMI_PCHIP0_WSBA3 (IDENT_ADDR + TS_BIAS + 0x1800000C0UL)
-
-#define TSUNAMI_PCHIP0_WSM0 (IDENT_ADDR + TS_BIAS + 0x180000100UL)
-#define TSUNAMI_PCHIP0_WSM1 (IDENT_ADDR + TS_BIAS + 0x180000140UL)
-#define TSUNAMI_PCHIP0_WSM2 (IDENT_ADDR + TS_BIAS + 0x180000180UL)
-#define TSUNAMI_PCHIP0_WSM3 (IDENT_ADDR + TS_BIAS + 0x1800001C0UL)
-#define TSUNAMI_PCHIP0_TBA0 (IDENT_ADDR + TS_BIAS + 0x180000200UL)
-#define TSUNAMI_PCHIP0_TBA1 (IDENT_ADDR + TS_BIAS + 0x180000240UL)
-#define TSUNAMI_PCHIP0_TBA2 (IDENT_ADDR + TS_BIAS + 0x180000280UL)
-#define TSUNAMI_PCHIP0_TBA3 (IDENT_ADDR + TS_BIAS + 0x1800002C0UL)
-
-#define TSUNAMI_PCHIP0_PCTL (IDENT_ADDR + TS_BIAS + 0x180000300UL)
-#define TSUNAMI_PCHIP0_PLAT (IDENT_ADDR + TS_BIAS + 0x180000340UL)
-#define TSUNAMI_PCHIP0_RESERVED (IDENT_ADDR + TS_BIAS + 0x180000380UL)
-#define TSUNAMI_PCHIP0_PERROR (IDENT_ADDR + TS_BIAS + 0x1800003c0UL)
-#define TSUNAMI_PCHIP0_PERRMASK (IDENT_ADDR + TS_BIAS + 0x180000400UL)
-#define TSUNAMI_PCHIP0_PERRSET (IDENT_ADDR + TS_BIAS + 0x180000440UL)
-#define TSUNAMI_PCHIP0_TLBIV (IDENT_ADDR + TS_BIAS + 0x180000480UL)
-#define TSUNAMI_PCHIP0_TLBIA (IDENT_ADDR + TS_BIAS + 0x1800004C0UL)
-#define TSUNAMI_PCHIP0_PMONCTL (IDENT_ADDR + TS_BIAS + 0x180000500UL)
-#define TSUNAMI_PCHIP0_PMONCNT (IDENT_ADDR + TS_BIAS + 0x180000540UL)
-
-#define TSUNAMI_PCHIP1_WSBA0 (IDENT_ADDR + TS_BIAS + 0x380000000UL)
-#define TSUNAMI_PCHIP1_WSBA1 (IDENT_ADDR + TS_BIAS + 0x380000040UL)
-#define TSUNAMI_PCHIP1_WSBA2 (IDENT_ADDR + TS_BIAS + 0x380000080UL)
-#define TSUNAMI_PCHIP1_WSBA3 (IDENT_ADDR + TS_BIAS + 0x3800000C0UL)
-#define TSUNAMI_PCHIP1_WSM0 (IDENT_ADDR + TS_BIAS + 0x380000100UL)
-#define TSUNAMI_PCHIP1_WSM1 (IDENT_ADDR + TS_BIAS + 0x380000140UL)
-#define TSUNAMI_PCHIP1_WSM2 (IDENT_ADDR + TS_BIAS + 0x380000180UL)
-#define TSUNAMI_PCHIP1_WSM3 (IDENT_ADDR + TS_BIAS + 0x3800001C0UL)
-
-#define TSUNAMI_PCHIP1_TBA0 (IDENT_ADDR + TS_BIAS + 0x380000200UL)
-#define TSUNAMI_PCHIP1_TBA1 (IDENT_ADDR + TS_BIAS + 0x380000240UL)
-#define TSUNAMI_PCHIP1_TBA2 (IDENT_ADDR + TS_BIAS + 0x380000280UL)
-#define TSUNAMI_PCHIP1_TBA3 (IDENT_ADDR + TS_BIAS + 0x3800002C0UL)
-
-#define TSUNAMI_PCHIP1_PCTL (IDENT_ADDR + TS_BIAS + 0x380000300UL)
-#define TSUNAMI_PCHIP1_PLAT (IDENT_ADDR + TS_BIAS + 0x380000340UL)
-#define TSUNAMI_PCHIP1_RESERVED (IDENT_ADDR + TS_BIAS + 0x380000380UL)
-#define TSUNAMI_PCHIP1_PERROR (IDENT_ADDR + TS_BIAS + 0x3800003c0UL)
-#define TSUNAMI_PCHIP1_PERRMASK (IDENT_ADDR + TS_BIAS + 0x380000400UL)
-#define TSUNAMI_PCHIP1_PERRSET (IDENT_ADDR + TS_BIAS + 0x380000440UL)
-#define TSUNAMI_PCHIP1_TLBIV (IDENT_ADDR + TS_BIAS + 0x380000480UL)
-#define TSUNAMI_PCHIP1_TLBIA (IDENT_ADDR + TS_BIAS + 0x3800004C0UL)
-#define TSUNAMI_PCHIP1_PMONCTL (IDENT_ADDR + TS_BIAS + 0x380000500UL)
-#define TSUNAMI_PCHIP1_PMONCNT (IDENT_ADDR + TS_BIAS + 0x380000540UL)
-
-/* */
-/* TSUNAMI Pchip Error register. */
-/* */
-#define perror_m_lost 0x1
-#define perror_m_serr 0x2
-#define perror_m_perr 0x4
-#define perror_m_dcrto 0x8
-#define perror_m_sge 0x10
-#define perror_m_ape 0x20
-#define perror_m_ta 0x40
-#define perror_m_rdpe 0x80
-#define perror_m_nds 0x100
-#define perror_m_rto 0x200
-#define perror_m_uecc 0x400
-#define perror_m_cre 0x800
-#define perror_m_addrl 0xFFFFFFFF0000UL
-#define perror_m_addrh 0x7000000000000UL
-#define perror_m_cmd 0xF0000000000000UL
-#define perror_m_syn 0xFF00000000000000UL
-union TPchipPERROR {
- struct {
- unsigned int perror_v_lost : 1;
- unsigned perror_v_serr : 1;
- unsigned perror_v_perr : 1;
- unsigned perror_v_dcrto : 1;
- unsigned perror_v_sge : 1;
- unsigned perror_v_ape : 1;
- unsigned perror_v_ta : 1;
- unsigned perror_v_rdpe : 1;
- unsigned perror_v_nds : 1;
- unsigned perror_v_rto : 1;
- unsigned perror_v_uecc : 1;
- unsigned perror_v_cre : 1;
- unsigned perror_v_rsvd1 : 4;
- unsigned perror_v_addrl : 32;
- unsigned perror_v_addrh : 3;
- unsigned perror_v_rsvd2 : 1;
- unsigned perror_v_cmd : 4;
- unsigned perror_v_syn : 8;
- } perror_r_bits;
- int perror_q_whole [2];
- } ;
-/* */
-/* TSUNAMI Pchip Window Space Base Address register. */
-/* */
-#define wsba_m_ena 0x1
-#define wsba_m_sg 0x2
-#define wsba_m_ptp 0x4
-#define wsba_m_addr 0xFFF00000
-#define wmask_k_sz1gb 0x3FF00000
-union TPchipWSBA {
- struct {
- unsigned wsba_v_ena : 1;
- unsigned wsba_v_sg : 1;
- unsigned wsba_v_ptp : 1;
- unsigned wsba_v_rsvd1 : 17;
- unsigned wsba_v_addr : 12;
- unsigned wsba_v_rsvd2 : 32;
- } wsba_r_bits;
- int wsba_q_whole [2];
- } ;
-/* */
-/* TSUNAMI Pchip Control Register */
-/* */
-#define pctl_m_fdsc 0x1
-#define pctl_m_fbtb 0x2
-#define pctl_m_thdis 0x4
-#define pctl_m_chaindis 0x8
-#define pctl_m_tgtlat 0x10
-#define pctl_m_hole 0x20
-#define pctl_m_mwin 0x40
-#define pctl_m_arbena 0x80
-#define pctl_m_prigrp 0x7F00
-#define pctl_m_ppri 0x8000
-#define pctl_m_rsvd1 0x30000
-#define pctl_m_eccen 0x40000
-#define pctl_m_padm 0x80000
-#define pctl_m_cdqmax 0xF00000
-#define pctl_m_rev 0xFF000000
-#define pctl_m_crqmax 0xF00000000UL
-#define pctl_m_ptpmax 0xF000000000UL
-#define pctl_m_pclkx 0x30000000000UL
-#define pctl_m_fdsdis 0x40000000000UL
-#define pctl_m_fdwdis 0x80000000000UL
-#define pctl_m_ptevrfy 0x100000000000UL
-#define pctl_m_rpp 0x200000000000UL
-#define pctl_m_pid 0xC00000000000UL
-#define pctl_m_rsvd2 0xFFFF000000000000UL
-
-union TPchipPCTL {
- struct {
- unsigned pctl_v_fdsc : 1;
- unsigned pctl_v_fbtb : 1;
- unsigned pctl_v_thdis : 1;
- unsigned pctl_v_chaindis : 1;
- unsigned pctl_v_tgtlat : 1;
- unsigned pctl_v_hole : 1;
- unsigned pctl_v_mwin : 1;
- unsigned pctl_v_arbena : 1;
- unsigned pctl_v_prigrp : 7;
- unsigned pctl_v_ppri : 1;
- unsigned pctl_v_rsvd1 : 2;
- unsigned pctl_v_eccen : 1;
- unsigned pctl_v_padm : 1;
- unsigned pctl_v_cdqmax : 4;
- unsigned pctl_v_rev : 8;
- unsigned pctl_v_crqmax : 4;
- unsigned pctl_v_ptpmax : 4;
- unsigned pctl_v_pclkx : 2;
- unsigned pctl_v_fdsdis : 1;
- unsigned pctl_v_fdwdis : 1;
- unsigned pctl_v_ptevrfy : 1;
- unsigned pctl_v_rpp : 1;
- unsigned pctl_v_pid : 2;
- unsigned pctl_v_rsvd2 : 16;
- } pctl_r_bits;
- int pctl_q_whole [2];
-} ;
-/* */
-/* TSUNAMI Pchip Error Mask Register. */
-/* */
-#define perrmask_m_lost 0x1
-#define perrmask_m_serr 0x2
-#define perrmask_m_perr 0x4
-#define perrmask_m_dcrto 0x8
-#define perrmask_m_sge 0x10
-#define perrmask_m_ape 0x20
-#define perrmask_m_ta 0x40
-#define perrmask_m_rdpe 0x80
-#define perrmask_m_nds 0x100
-#define perrmask_m_rto 0x200
-#define perrmask_m_uecc 0x400
-#define perrmask_m_cre 0x800
-#define perrmask_m_rsvd 0xFFFFFFFFFFFFF000UL
-union TPchipPERRMASK {
- struct {
- unsigned int perrmask_v_lost : 1;
- unsigned perrmask_v_serr : 1;
- unsigned perrmask_v_perr : 1;
- unsigned perrmask_v_dcrto : 1;
- unsigned perrmask_v_sge : 1;
- unsigned perrmask_v_ape : 1;
- unsigned perrmask_v_ta : 1;
- unsigned perrmask_v_rdpe : 1;
- unsigned perrmask_v_nds : 1;
- unsigned perrmask_v_rto : 1;
- unsigned perrmask_v_uecc : 1;
- unsigned perrmask_v_cre : 1;
- unsigned perrmask_v_rsvd1 : 20;
- unsigned perrmask_v_rsvd2 : 32;
- } perrmask_r_bits;
- int perrmask_q_whole [2];
- } ;
-
-/*
- * Memory spaces:
- */
-#define TSUNAMI_PCI0_MEM (IDENT_ADDR + TS_BIAS + 0x000000000UL)
-#define TSUNAMI_PCI0_IACK_SC (IDENT_ADDR + TS_BIAS + 0x1F8000000UL)
-#define TSUNAMI_PCI0_IO (IDENT_ADDR + TS_BIAS + 0x1FC000000UL)
-#define TSUNAMI_PCI0_CONF (IDENT_ADDR + TS_BIAS + 0x1FE000000UL)
-
-#define TSUNAMI_PCI1_MEM (IDENT_ADDR + TS_BIAS + 0x200000000UL)
-#define TSUNAMI_PCI1_IACK_SC (IDENT_ADDR + TS_BIAS + 0x3F8000000UL)
-#define TSUNAMI_PCI1_IO (IDENT_ADDR + TS_BIAS + 0x3FC000000UL)
-#define TSUNAMI_PCI1_CONF (IDENT_ADDR + TS_BIAS + 0x3FE000000UL)
-
-#define HAE_ADDRESS 0
-
-#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) + TSUNAMI_DMA_WIN_BASE;
-}
-
-extern inline void * bus_to_virt(unsigned long address)
-{
- return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE);
-}
-
-/*
- * I/O functions:
- *
- * TSUNAMI, the 21??? PCI/memory support chipset for the EV6 (21264)
- * can only use linear accesses to get at PCI memory and I/O spaces.
- */
-
-/* HACK ALERT! HACK ALERT! */
-/* HACK ALERT! HACK ALERT! */
-
-/* only using PCI bus 0 for now in all routines */
-
-#define DENSE_MEM(addr) TSUNAMI_PCI0_MEM
-
-/* HACK ALERT! HACK ALERT! */
-/* HACK ALERT! HACK ALERT! */
-
-/* Also assume we are optimizing for EV6, and so the compiler knows about
- byte/word instructions. */
-
-#define vucp volatile unsigned char *
-#define vusp volatile unsigned short *
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-extern inline unsigned int __inb(unsigned long addr)
-{
- return *(vucp)(addr + TSUNAMI_PCI0_IO);
-}
-
-extern inline void __outb(unsigned char b, unsigned long addr)
-{
- *(vucp)(addr + TSUNAMI_PCI0_IO) = b;
- mb();
-}
-
-extern inline unsigned int __inw(unsigned long addr)
-{
- return *(vusp)(addr+TSUNAMI_PCI0_IO);
-}
-
-extern inline void __outw(unsigned short b, unsigned long addr)
-{
- *(vusp)(addr+TSUNAMI_PCI0_IO) = b;
- mb();
-}
-
-extern inline unsigned int __inl(unsigned long addr)
-{
- return *(vuip)(addr+TSUNAMI_PCI0_IO);
-}
-
-extern inline void __outl(unsigned int b, unsigned long addr)
-{
- *(vuip)(addr+TSUNAMI_PCI0_IO) = b;
- mb();
-}
-
-/*
- * Memory functions. all accesses are done through linear space.
- */
-
-extern inline unsigned long __readb(unsigned long addr)
-{
- return *(vucp)(addr+TSUNAMI_PCI0_MEM);
-}
-
-extern inline unsigned long __readw(unsigned long addr)
-{
- return *(vusp)(addr+TSUNAMI_PCI0_MEM);
-}
-
-extern inline unsigned long __readl(unsigned long addr)
-{
- return *(vuip)(addr+TSUNAMI_PCI0_MEM);
-}
-
-extern inline unsigned long __readq(unsigned long addr)
-{
- return *(vulp)(addr+TSUNAMI_PCI0_MEM);
-}
-
-extern inline void __writeb(unsigned char b, unsigned long addr)
-{
- *(vucp)(addr+TSUNAMI_PCI0_MEM) = b;
- mb();
-}
-
-extern inline void __writew(unsigned short b, unsigned long addr)
-{
- *(vusp)(addr+TSUNAMI_PCI0_MEM) = b;
- mb();
-}
-
-extern inline void __writel(unsigned int b, unsigned long addr)
-{
- *(vuip)(addr+TSUNAMI_PCI0_MEM) = b;
- mb();
-}
-
-extern inline void __writeq(unsigned long b, unsigned long addr)
-{
- *(vulp)(addr+TSUNAMI_PCI0_MEM) = b;
- mb();
-}
-
-#define inb(port) __inb((port))
-#define inw(port) __inw((port))
-#define inl(port) __inl((port))
-
-#define outb(v, port) __outb((v),(port))
-#define outw(v, port) __outw((v),(port))
-#define outl(v, port) __outl((v),(port))
-
-#define readb(a) __readb((unsigned long)(a))
-#define readw(a) __readw((unsigned long)(a))
-#define readl(a) __readl((unsigned long)(a))
-#define readq(a) __readq((unsigned long)(a))
-
-#define writeb(v,a) __writeb((v),(unsigned long)(a))
-#define writew(v,a) __writew((v),(unsigned long)(a))
-#define writel(v,a) __writel((v),(unsigned long)(a))
-#define writeq(v,a) __writeq((v),(unsigned long)(a))
-
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-extern unsigned long tsunami_init (unsigned long, unsigned long);
-
-#endif /* __KERNEL__ */
-
-/*
- * Data structure for handling TSUNAMI machine checks:
- */
-struct el_TSUNAMI_sysdata_mcheck {
-};
-
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
-
-#endif /* __ALPHA_TSUNAMI__H__ */
: "cc");
}
-/*
- * Cyrix CPU configuration register indexes
- */
-#define CX86_CCR2 0xc2
-#define CX86_CCR3 0xc3
-#define CX86_CCR4 0xe8
-#define CX86_CCR5 0xe9
-#define CX86_DIR0 0xfe
-#define CX86_DIR1 0xff
-
-/*
- * Cyrix CPU indexed register access macros
- */
-
-extern inline unsigned char getCx86(unsigned char reg)
-{
- unsigned char data;
-
- __asm__ __volatile__("movb %1,%%al\n\t"
- "outb %%al,$0x22\n\t"
- "inb $0x23,%%al" : "=a" (data) : "q" (reg));
- return data;
-}
-
-extern inline void setCx86(unsigned char reg, unsigned char data)
-{
- __asm__ __volatile__("outb %%al,$0x22\n\t"
- "movb %1,%%al\n\t"
- "outb %%al,$0x23" : : "a" (reg), "q" (data));
-}
-
/*
* Bus types (default is ISA, but people can check others with these..)
*/
#define __NR_lseek 19
#define __NR_getpid 20
#define __NR_mount 21
-#define __NR_umount 22
+#define __NR_oldumount 22
#define __NR_setuid 23
#define __NR_getuid 24
#define __NR_stime 25
#define __NR_geteuid 49
#define __NR_getegid 50
#define __NR_acct 51
-#define __NR_phys 52
+#define __NR_umount 52
#define __NR_lock 53
#define __NR_ioctl 54
#define __NR_fcntl 55
#define DOS_EXTENDED_PARTITION 5
#define LINUX_EXTENDED_PARTITION 0x85
#define WIN98_EXTENDED_PARTITION 0x0f
+
#define LINUX_SWAP_PARTITION 0x82
#ifdef CONFIG_SOLARIS_X86_PARTITION
{
struct sk_buff_head sendq;
__u32 bytespertick;
+ __u32 bitspersec;
__u32 shapelatency;
__u32 shapeclock;
__u32 recovery; /* Time we can next clock a packet out on
#define SHAPER_SET_DEV 0x0001
#define SHAPER_SET_SPEED 0x0002
+#define SHAPER_GET_DEV 0x0003
+#define SHAPER_GET_SPEED 0x0004
struct shaperconf
{
+++ /dev/null
-#ifndef _LINUX_IF_WIC_H
-#define _LINUX_IF_WIC_H
-
-#include <linux/sockios.h>
-
-#define SIOCDEVWIC SIOCDEVPRIVATE
-
-struct wicconf
-{
- unsigned char pcmd;
- unsigned char data[120];
- unsigned char len;
-};
-
-/* WIC host to controller commands */
-
-#define WIC_AYT 0x10 /* test dki */
-#define WIC_RESET 0x11 /* reset controller */
-#define WIC_SETSN 0x21 /* set station name */
-#define WIC_SETPS 0x22 /* set power saving mode */
-#define WIC_SETAF 0x23 /* set announce filter */
-#define WIC_SETGPF 0x24 /* set GPSP filter */
-#define WIC_GETVERH 0x61 /* get interface controller version */
-#define WIC_GETNL 0x62 /* get neighbor list */
-#define WIC_GETSN 0x65 /* get station name */
-#define WIC_CLRSTATS 0x83 /* clear controller statistics */
-#define WIC_SETNET 0x84 /* set network configuration */
-#define WIC_SETSYS 0x85 /* set system configuration */
-#define WIC_GETSTATS 0xc1 /* get statistics */
-#define WIC_GETVERM 0xc3 /* get MAC version */
-#define WIC_GETNET 0xc4 /* get network configuration */
-#define WIC_GETSYS 0xc5 /* get system configuration */
-
-/*
- * structure used for the GETNET/SETNET command
- */
-
-struct wic_net {
- unsigned char ula[6]; /* ula of interface */
- unsigned char mode; /* operating mode */
-#define NET_MODE_ME 0x01 /* receive my ula */
-#define NET_MODE_BCAST 0x02 /* receive bcasts */
-#define NET_MODE_MCAST 0x04 /* receive mcasts */
-#define NET_MODE_PROM 0x08 /* promiscuous */
-#define NET_MODE_HC 0x10 /* is a hop coordinator */
-#define NET_MODE_HC_VALID 0x20 /* hc address is valid */
-#define NET_MODE_HCAP 0x40 /* hc is also ap */
-#define NET_MODE_HC_KNOWN 0x80 /* hc is known */
- unsigned char rts_lo; /* rts threshold */
- unsigned char rts_hi; /* rts threshold */
- unsigned char retry; /* retry limit */
- unsigned char hc_ula[6]; /* ula of hc */
- unsigned char key[4]; /* network key */
- unsigned char dsl; /* direct send limit */
- unsigned char res1; /* reserved */
-};
-
-/*
- * structure used for the GETSYS/SETSYS command
- */
-
-struct wic_sys {
- unsigned char mode; /* set operating mode */
-#define SYS_MODE_ANT_DIV 0x00 /* use antenna diversity */
-#define SYS_MODE_ANT_1 0x01 /* use ant 1 for tx */
-#define SYS_MODE_ANT_2 0x02 /* use ant 2 for tx */
-#define SYS_MODE_HC_LOCK 0x04 /* lock onto current hc */
-#define SYS_MODE_DEBUG 0x08 /* upload failed frames */
-#define SYS_MODE_IAM_AP 0x10 /* I am AP */
-#define SYS_MODE_IAM_HC 0x20 /* I am HC */
-#define SYS_MODE_USE_SKIP 0x40 /* use skipping mechanism */
-#define SYS_MODE_AUTO 0x80 /* station is in auto mode */
- unsigned char switches; /* radio/controller switches */
-#define SYS_SWITCH_STDBY 0x01 /* switch radio to standby */
-#define SYS_SWITCH_TXRX 0x02 /* 1 = tx, manual mode only */
-#define SYS_SWITCH_PA 0x04 /* 1 = enable PA on radio */
-#define SYS_SWITCH_PWR 0x10 /* 1 = hi, 0 = lo power output */
-#define SYS_SWITCH_RES1 0x20 /* reserved, must be 0 */
-#define SYS_SWITCH_LIGHTS 0x40 /* light for tx & rx */
-#define SYS_SWITCH_LIGHTS_HC 0x80 /* light for rx while coordinated */
- unsigned char hop_min; /* hop range */
- unsigned char hop_max; /* hop range */
- unsigned char pre_len; /* preamble length (bytes) */
- unsigned char pre_match; /* valid preamble match (bytes) */
- unsigned char mod; /* data mod: 1 = 8:1, 0 = none */
- unsigned char cca_mode; /* cca flags */
-#define CCA_PKT_DET_BSY 0x01 /* busy if packet is detected */
-#define CCA_VIRT_CARR 0x02 /* use virtual carrier */
-#define CCA_RSSI_BSY 0x04 /* busy if rssi > threshold */
-#define CCA_DATA_BSY 0x08 /* busy if valid data > XXX usec */
- unsigned char dwell_hi; /* dwell time */
- unsigned char dwell_lo; /* dwell time */
- unsigned char hc_timeout; /* HC timeout */
- unsigned char rssi; /* rssi threshold */
- unsigned char hc_rssi; /* rssi of last hc frame */
- unsigned char hc_rssi_chan; /* channel of hc rssi value */
-};
-
-
-#endif /* _LINUX_IF_WIC_H */
-
-
struct vfsmount *lookup_vfsmnt(kdev_t dev);
+/*
+ * Umount options
+ */
+
+#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */
+
#endif /* _LINUX_MOUNT_H */
PROC_MODULES,
PROC_STAT,
PROC_DEVICES,
+ PROC_PARTITIONS,
PROC_INTERRUPTS,
PROC_FILESYSTEMS,
PROC_KSYMS,
#ifdef __KERNEL__
+#include <linux/poll.h>
+
struct video_device
{
char name[32];
long (*read)(struct video_device *, char *, unsigned long, int noblock);
/* Do we need a write method ? */
long (*write)(struct video_device *, const char *, unsigned long, int noblock);
+ unsigned int (*poll)(struct video_device *, struct file *, poll_table *);
int (*ioctl)(struct video_device *, unsigned int , void *);
int (*mmap)(struct video_device *, const char *, unsigned long);
int (*initialize)(struct video_device *);
#define VIDEO_PALETTE_YUYV 8
#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
#define VIDEO_PALETTE_YUV420 10
+#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
+#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
};
struct video_audio
{
unsigned int frame; /* Frame (0 or 1) for double buffer */
int height,width;
- unsigned int format;
+ unsigned int format; /* should be VIDEO_PALETTE_* */
};
struct video_key
#define VID_HARDWARE_ZOLTRIX 10
#define VID_HARDWARE_SAA7146 11
#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
+#define VID_HARDWARE_RTRACK2 13
/*
* Initialiser list
static int max_msqid = 0;
static struct wait_queue *msg_lock = NULL;
-__initfunc(void msg_init (void))
+void __init msg_init (void)
{
int id;
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;
- unsigned long flags;
if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
- if (!msgp)
- return -EFAULT;
- err = verify_area (VERIFY_READ, msgp->mtext, msgsz);
- if (err)
- return err;
- get_user(mtype, &msgp->mtype);
+ if (get_user(mtype, &msgp->mtype))
+ return -EFAULT;
if (mtype < 1)
return -EINVAL;
id = (unsigned int) msqid % MSGMNI;
msgh->msg_type = mtype;
msgh->msg_stime = CURRENT_TIME;
- save_flags(flags);
- cli();
if (!msq->msg_first)
msq->msg_first = msq->msg_last = msgh;
else {
msq->msg_qnum++;
msq->msg_lspid = current->pid;
msq->msg_stime = CURRENT_TIME;
- restore_flags(flags);
wake_up (&msq->rwait);
return 0;
}
struct msg *tmsg, *leastp = NULL;
struct msg *nmsg = NULL;
int id, err;
- unsigned long flags;
if (msqid < 0 || (long) msgsz < 0)
return -EINVAL;
- if (!msgp || !msgp->mtext)
- return -EFAULT;
-
- err = verify_area (VERIFY_WRITE, msgp->mtext, msgsz);
- if (err)
- return err;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
return -EACCES;
}
- save_flags(flags);
- cli();
if (msgtyp == 0)
nmsg = msq->msg_first;
else if (msgtyp > 0) {
if (leastp && leastp->msg_type <= - msgtyp)
nmsg = leastp;
}
- restore_flags(flags);
if (nmsg) { /* done finding a message */
if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) {
return -E2BIG;
}
msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
- save_flags(flags);
- cli();
if (nmsg == msq->msg_first)
msq->msg_first = nmsg->msg_next;
else {
msgbytes -= nmsg->msg_ts;
msghdrs--;
msq->msg_cbytes -= nmsg->msg_ts;
- restore_flags(flags);
wake_up (&msq->wwait);
- put_user (nmsg->msg_type, &msgp->mtype);
- copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz);
+ if (put_user (nmsg->msg_type, &msgp->mtype) ||
+ copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz))
+ msgsz = -EFAULT;
kfree(nmsg);
return msgsz;
} else { /* did not find a message */
msginfo.msgmap = msghdrs;
msginfo.msgtql = msgbytes;
}
- err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));
- if (err)
- goto out;
- copy_to_user (buf, &msginfo, sizeof(struct msginfo));
+
+ err = -EFAULT;
+ if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
+ goto out;
err = max_msqid;
goto out;
}
case MSG_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
- if (err)
- goto out;
err = -EINVAL;
if (msqid > max_msqid)
goto out;
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof(*buf));
+ err = -EFAULT;
+ if (copy_to_user (buf, &tbuf, sizeof(*buf)))
+ goto out;
err = id;
goto out;
case IPC_SET:
if (!buf)
goto out;
- err = verify_area (VERIFY_READ, buf, sizeof (*buf));
- if (err)
- goto out;
- copy_from_user (&tbuf, buf, sizeof (*buf));
+ err = -EFAULT;
+ if (!copy_from_user (&tbuf, buf, sizeof (*buf)))
+ err = 0;
break;
case IPC_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof(*buf));
- if (err)
- goto out;
break;
}
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof (*buf));
- err = 0;
+ err = -EFAULT;
+ if (!copy_to_user (buf, &tbuf, sizeof (*buf)))
+ err = 0;
goto out;
case IPC_SET:
err = -EPERM;
#include <linux/ctype.h>
#include <linux/file.h>
#include <linux/console.h>
+#include <linux/time.h>
extern unsigned char aux_device_present, pckbd_read_mask;
#ifdef CONFIG_BLK_DEV_MD
EXPORT_SYMBOL(disk_name); /* for md.c */
#endif
-
+
/* binfmt_aout */
EXPORT_SYMBOL(get_write_access);
EXPORT_SYMBOL(put_write_access);
/* dynamic registering of consoles */
EXPORT_SYMBOL(register_console);
EXPORT_SYMBOL(unregister_console);
+
+/* time */
+EXPORT_SYMBOL(get_fast_time);
swapstat_t swapstats = {0};
buffer_mem_t buffer_mem = {
- 3, /* minimum percent buffer */
- 10, /* borrow percent buffer */
- 30 /* maximum percent buffer */
+ 5, /* minimum percent buffer */
+ 25, /* borrow percent buffer */
+ 50 /* maximum percent buffer */
};
buffer_mem_t page_cache = {
if (sk->zapped == 0)
return -EINVAL;
- if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
+ if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25))
+ return -EINVAL;
+
+ if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25)))
return -EINVAL;
if (addr->fsa_ax25.sax25_family != AF_AX25)
* recovering the MAC header first.
*/
- int offset=skb->data-skb->mac.raw;
- cli();
+ int offset;
+
+ skb=skb_clone(skb, GFP_ATOMIC);
+ if(skb==NULL)
+ return;
+
+ offset=skb->data-skb->mac.raw;
skb_push(skb,offset); /* Put header back on for bridge */
+
if(br_receive_frame(skb))
- {
- sti();
return;
- }
- /*
- * Pull the MAC header off for the copy going to
- * the upper layers.
- */
- skb_pull(skb,offset);
- sti();
+ kfree_skb(skb, FREE_READ);
}
+ return;
}
#endif
#include <linux/inet.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
+#include <linux/wireless.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/inet_common.h>
static struct proto_ops econet_ops;
static struct sock *econet_sklist;
+static spinlock_t aun_queue_lock;
+
#ifdef CONFIG_ECONET_AUNUDP
static struct socket *udpsock;
#define AUN_PORT 0x8000
eb->cookie = saddr->cookie;
eb->sec = *saddr;
- eb->sent - ec_tx_done;
+ eb->sent = ec_tx_done;
if (dev->hard_header) {
int res;
* drop the packet.
*/
-static spinlock_t aun_queue_lock;
static void ab_cleanup(unsigned long h)
{
dev_queue_xmit
};
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25) || \
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) || \
defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE)
struct neigh_ops arp_broken_ops =
{
default:
break;
case ARPHRD_ROSE:
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25)
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
case ARPHRD_AX25:
#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
case ARPHRD_NETROM:
packet_release,
packet_bind,
sock_no_connect,
- NULL,
- NULL,
+ sock_no_socketpair,
+ sock_no_accept,
packet_getname,
datagram_poll,
packet_ioctl,