From 7d32756b2c8c01985da2609d3efebc5a02bfec58 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:16:18 -0500 Subject: [PATCH] Import 2.1.116pre1 --- CREDITS | 4 +- Documentation/magic-number.txt | 33 +- Documentation/radiotrack.txt | 147 ++ Documentation/sound/ChangeLog.multisound | 137 ++ Documentation/sound/MultiSound | 106 +- Documentation/sound/OPL3-SA | 11 +- Documentation/sound/Wavefront | 142 +- MAINTAINERS | 4 +- Makefile | 2 +- arch/alpha/Makefile | 55 +- arch/alpha/config.in | 53 +- arch/alpha/defconfig | 35 +- arch/alpha/kernel/Makefile | 89 +- arch/alpha/kernel/alpha_ksyms.c | 4 + arch/alpha/kernel/bios32.c | 2165 ++++------------- arch/alpha/kernel/bios32.h | 155 ++ arch/alpha/kernel/{apecs.c => core_apecs.c} | 398 ++- arch/alpha/kernel/{cia.c => core_cia.c} | 490 ++-- arch/alpha/kernel/{lca.c => core_lca.c} | 269 +- arch/alpha/kernel/core_mcpcia.c | 969 ++++++++ arch/alpha/kernel/core_pyxis.c | 634 +++++ arch/alpha/kernel/{t2.c => core_t2.c} | 372 ++- arch/alpha/kernel/core_tsunami.c | 446 ++++ arch/alpha/kernel/entry.S | 8 +- arch/alpha/kernel/es1888.c | 47 + arch/alpha/kernel/fpreg.c | 92 +- arch/alpha/kernel/head.S | 1 - arch/alpha/kernel/irq.c | 1659 ++----------- arch/alpha/kernel/irq.h | 27 + arch/alpha/kernel/machvec.h | 136 ++ arch/alpha/kernel/mcpcia.c | 975 -------- arch/alpha/kernel/osf_sys.c | 4 +- arch/alpha/kernel/process.c | 173 +- arch/alpha/kernel/proto.h | 131 + arch/alpha/kernel/ptrace.c | 4 +- arch/alpha/kernel/pyxis.c | 663 ----- arch/alpha/kernel/setup.c | 761 ++++-- arch/alpha/kernel/smp.c | 14 +- arch/alpha/kernel/sys_alcor.c | 263 ++ arch/alpha/kernel/sys_cabriolet.c | 395 +++ arch/alpha/kernel/sys_dp264.c | 231 ++ arch/alpha/kernel/sys_eb64p.c | 206 ++ arch/alpha/kernel/sys_jensen.c | 146 ++ arch/alpha/kernel/sys_miata.c | 307 +++ arch/alpha/kernel/sys_mikasa.c | 297 +++ arch/alpha/kernel/sys_noritake.c | 301 +++ arch/alpha/kernel/sys_rawhide.c | 195 ++ arch/alpha/kernel/sys_ruffian.c | 267 ++ arch/alpha/kernel/sys_sable.c | 297 +++ arch/alpha/kernel/sys_sio.c | 470 ++++ arch/alpha/kernel/sys_sx164.c | 217 ++ arch/alpha/kernel/sys_takara.c | 165 ++ arch/alpha/kernel/traps.c | 77 +- arch/alpha/kernel/tsunami.c | 503 ---- arch/alpha/lib/Makefile | 2 +- arch/alpha/lib/io.c | 49 +- arch/alpha/lib/strcasecmp.c | 26 + arch/alpha/math-emu/fp-emul.c | 32 +- arch/alpha/mm/fault.c | 54 +- arch/alpha/mm/init.c | 72 +- arch/i386/kernel/entry.S | 4 +- arch/i386/kernel/head.S | 3 - arch/i386/kernel/setup.c | 26 +- drivers/block/genhd.c | 28 +- drivers/block/loop.c | 11 +- drivers/block/trm290.c | 2 +- drivers/char/apm_bios.c | 3 + drivers/char/bttv.c | 105 +- drivers/char/bw-qcam.c | 1 + drivers/char/c-qcam.c | 1 + drivers/char/cyclades.c | 2 +- drivers/char/keyboard.c | 3 +- drivers/char/lp.c | 2 +- drivers/char/msp3400.c | 5 +- drivers/char/pc_keyb.c | 2 +- drivers/char/pms.c | 1 + drivers/char/pty.c | 1 + drivers/char/radio-aimslab.c | 7 +- drivers/char/radio-aztech.c | 4 +- drivers/char/radio-rtrack2.c | 272 +++ drivers/char/radio-sf16fmi.c | 35 +- drivers/char/radio-zoltrix.c | 74 +- drivers/char/videodev.c | 18 +- drivers/net/3c509.c | 6 +- drivers/net/plip.c | 43 +- drivers/net/shaper.c | 13 +- drivers/net/tlan.c | 9 +- drivers/net/tlan.h | 22 +- drivers/video/tgafb.c | 4 +- drivers/video/vgacon.c | 4 + fs/exec.c | 11 +- fs/nfsd/vfs.c | 5 +- fs/proc/array.c | 6 + fs/proc/generic.c | 6 +- fs/proc/root.c | 6 + fs/super.c | 26 +- fs/vfat/namei.c | 2 + include/asm-alpha/bitops.h | 54 +- include/asm-alpha/compiler.h | 74 + include/asm-alpha/{apecs.h => core_apecs.h} | 499 ++-- include/asm-alpha/{cia.h => core_cia.h} | 525 ++-- include/asm-alpha/{lca.h => core_lca.h} | 273 ++- include/asm-alpha/{mcpcia.h => core_mcpcia.h} | 532 ++-- include/asm-alpha/{pyxis.h => core_pyxis.h} | 592 +++-- include/asm-alpha/{t2.h => core_t2.h} | 776 +++--- .../asm-alpha/{tsunami.h => core_tsunami.h} | 141 +- include/asm-alpha/dma.h | 22 +- include/asm-alpha/floppy.h | 25 +- include/asm-alpha/hwrpb.h | 11 +- include/asm-alpha/init.h | 6 - include/asm-alpha/io.h | 165 +- include/asm-alpha/irq.h | 51 +- include/asm-alpha/jensen.h | 220 +- include/asm-alpha/machvec.h | 118 + include/asm-alpha/mmu_context.h | 118 +- include/asm-alpha/pci.h | 48 + include/asm-alpha/pgtable.h | 96 +- include/asm-alpha/posix_types.h | 4 + include/asm-alpha/processor.h | 18 +- include/asm-alpha/string.h | 2 + include/asm-alpha/system.h | 5 +- include/asm-i386/processor.h | 31 - include/asm-i386/unistd.h | 4 +- include/linux/genhd.h | 1 + include/linux/if_shaper.h | 3 + include/linux/if_wic.h | 102 - include/linux/mount.h | 6 + include/linux/proc_fs.h | 1 + include/linux/videodev.h | 10 +- ipc/msg.c | 62 +- kernel/ksyms.c | 6 +- mm/swap.c | 6 +- net/ax25/af_ax25.c | 5 +- net/core/dev.c | 21 +- net/econet/econet.c | 6 +- net/ipv4/arp.c | 4 +- net/packet/af_packet.c | 4 +- 137 files changed, 12381 insertions(+), 9026 deletions(-) create mode 100644 Documentation/radiotrack.txt create mode 100644 Documentation/sound/ChangeLog.multisound create mode 100644 arch/alpha/kernel/bios32.h rename arch/alpha/kernel/{apecs.c => core_apecs.c} (51%) rename arch/alpha/kernel/{cia.c => core_cia.c} (55%) rename arch/alpha/kernel/{lca.c => core_lca.c} (71%) create mode 100644 arch/alpha/kernel/core_mcpcia.c create mode 100644 arch/alpha/kernel/core_pyxis.c rename arch/alpha/kernel/{t2.c => core_t2.c} (61%) create mode 100644 arch/alpha/kernel/core_tsunami.c create mode 100644 arch/alpha/kernel/es1888.c create mode 100644 arch/alpha/kernel/irq.h create mode 100644 arch/alpha/kernel/machvec.h delete mode 100644 arch/alpha/kernel/mcpcia.c create mode 100644 arch/alpha/kernel/proto.h delete mode 100644 arch/alpha/kernel/pyxis.c create mode 100644 arch/alpha/kernel/sys_alcor.c create mode 100644 arch/alpha/kernel/sys_cabriolet.c create mode 100644 arch/alpha/kernel/sys_dp264.c create mode 100644 arch/alpha/kernel/sys_eb64p.c create mode 100644 arch/alpha/kernel/sys_jensen.c create mode 100644 arch/alpha/kernel/sys_miata.c create mode 100644 arch/alpha/kernel/sys_mikasa.c create mode 100644 arch/alpha/kernel/sys_noritake.c create mode 100644 arch/alpha/kernel/sys_rawhide.c create mode 100644 arch/alpha/kernel/sys_ruffian.c create mode 100644 arch/alpha/kernel/sys_sable.c create mode 100644 arch/alpha/kernel/sys_sio.c create mode 100644 arch/alpha/kernel/sys_sx164.c create mode 100644 arch/alpha/kernel/sys_takara.c delete mode 100644 arch/alpha/kernel/tsunami.c create mode 100644 arch/alpha/lib/strcasecmp.c create mode 100644 drivers/char/radio-rtrack2.c create mode 100644 include/asm-alpha/compiler.h rename include/asm-alpha/{apecs.h => core_apecs.h} (61%) rename include/asm-alpha/{cia.h => core_cia.h} (57%) rename include/asm-alpha/{lca.h => core_lca.h} (73%) rename include/asm-alpha/{mcpcia.h => core_mcpcia.h} (54%) rename include/asm-alpha/{pyxis.h => core_pyxis.h} (58%) rename include/asm-alpha/{t2.h => core_t2.h} (64%) rename include/asm-alpha/{tsunami.h => core_tsunami.h} (81%) create mode 100644 include/asm-alpha/machvec.h create mode 100644 include/asm-alpha/pci.h delete mode 100644 include/linux/if_wic.h diff --git a/CREDITS b/CREDITS index 7180abd9196a..2035ac51a84d 100644 --- a/CREDITS +++ b/CREDITS @@ -706,8 +706,8 @@ N: Richard Henderson 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 diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index ca5c3e20c62e..4449732ab81a 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -26,7 +26,7 @@ structures following the array have been overwritten. Using this 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. @@ -34,42 +34,65 @@ The magic table is current to Linux 2.1.55. 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 + + 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 diff --git a/Documentation/radiotrack.txt b/Documentation/radiotrack.txt new file mode 100644 index 000000000000..fe942e8a9ff5 --- /dev/null +++ b/Documentation/radiotrack.txt @@ -0,0 +1,147 @@ +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) + +---------------------------------------------------------------------------- diff --git a/Documentation/sound/ChangeLog.multisound b/Documentation/sound/ChangeLog.multisound new file mode 100644 index 000000000000..a25f465b71a3 --- /dev/null +++ b/Documentation/sound/ChangeLog.multisound @@ -0,0 +1,137 @@ +1998-08-06 Andrew Veliath + + * 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 + + * Update version to 0.7.1 + + * Add more OSS ioctls + +1998-07-19 Andrew Veliath + + * 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 + + * 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 + + * 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 + + * 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 + + * Update version to 0.5 + + * Separate reset queue functions for play and record + + * Add delays in dsp_halt + +1998-05-24 Andrew Veliath + + * 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 + + * Update version to 0.4c + + * Hopefully fix the mixer volume problem + +1998-05-19 Andrew Veliath + + * 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 + + * 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 + + * Update version to 0.4 + + * Fix read/write return values + +1998-05-13 Andrew Veliath + + * 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 + + * Update version to 0.2 + + * Add preliminary playback support + + * Use new Turtle Beach DSP code \ No newline at end of file diff --git a/Documentation/sound/MultiSound b/Documentation/sound/MultiSound index de85125f40cc..4d4313134b5a 100644 --- a/Documentation/sound/MultiSound +++ b/Documentation/sound/MultiSound @@ -9,8 +9,8 @@ Supported Features ~~~~~~~~~~~~~~~~~~ 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 @@ -80,14 +80,28 @@ mem Shared memory area, e.g. mem=0xd8000 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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -105,7 +119,9 @@ following firmware files to /etc/sound (note the file renaming): 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 @@ -122,9 +138,9 @@ and end lines): -- 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 -- @@ -143,4 +159,76 @@ archive unpacked into a directory named PINNDDK): 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 +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int fd; + unsigned long recmask, recsrc; + + if (argc != 2) { + fprintf(stderr, "usage: setdigital \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 -- diff --git a/Documentation/sound/OPL3-SA b/Documentation/sound/OPL3-SA index 62f798930920..153082c463de 100644 --- a/Documentation/sound/OPL3-SA +++ b/Documentation/sound/OPL3-SA @@ -1,6 +1,12 @@ -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. @@ -73,4 +79,3 @@ A 'cat /dev/sndstat' with all the above options should look similar to this: Questions? Comments? - diff --git a/Documentation/sound/Wavefront b/Documentation/sound/Wavefront index 4a2ad4b9eced..aadbfd23ff43 100644 --- a/Documentation/sound/Wavefront +++ b/Documentation/sound/Wavefront @@ -1,14 +1,17 @@ - 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 @@ -17,11 +20,11 @@ provides bug-free support for the Tropez Plus. 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 -------------- @@ -30,7 +33,7 @@ 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 @@ -40,14 +43,13 @@ Some Questions * 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 ? ********************************************************************** @@ -81,24 +83,27 @@ out. Reports welcome. 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 @@ -113,6 +118,9 @@ PART ONE: install the source code into your sound driver directory 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 @@ -121,15 +129,14 @@ PART THREE: configure your kernel cd 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 @@ -155,7 +162,6 @@ Here's my autoconf.h SOUND section: #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 @@ -191,21 +197,22 @@ relevant details): 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. @@ -218,7 +225,7 @@ for the ICS2115. However, if you have a WaveFront card, then you 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+). @@ -233,7 +240,7 @@ processed version: %% ^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext); <> { fputc ('\0', stdout); return; } -\n {} +\n {} . {} ---- cut here ------------------------- @@ -241,7 +248,7 @@ To use it, put the above in file (say, ws.l) compile it like this: 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 @@ -260,12 +267,11 @@ Then, as root do: 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. @@ -294,9 +300,9 @@ Load type: Driver loaded as a module 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) @@ -325,7 +331,7 @@ which is the default (I think ...). If you have an external synth(s) 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 ? @@ -333,39 +339,28 @@ should). 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? @@ -374,4 +369,3 @@ strings: Just me: Paul Barton-Davis - diff --git a/MAINTAINERS b/MAINTAINERS index 8d565e586d49..9fbebebbd1c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -330,9 +330,9 @@ S: Maintained 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) diff --git a/Makefile b/Makefile index 079e835c915c..62981e9d300e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ 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/) diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 77dde66141f3..d497ec3c80be 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -10,35 +10,42 @@ 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 @@ -59,7 +66,7 @@ rawboot: @$(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: diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 7eda886d91ce..9d0f5769ec50 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -31,30 +31,30 @@ else 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 @@ -64,6 +64,11 @@ unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS 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 diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 7f0ffbf2069a..64a051c16590 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -18,35 +18,32 @@ CONFIG_MODULES=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 diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 8d09ea8c438b..fcbb37615fad 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -20,34 +20,96 @@ O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \ 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 @@ -55,9 +117,4 @@ endif 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 diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index f66ace9a0be5..a7047dd1f4f4 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -25,6 +25,7 @@ #include #include #include +#include #define __KERNEL_SYSCALLS__ #include @@ -43,6 +44,7 @@ extern void __remlu (void); 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); @@ -121,7 +123,9 @@ EXPORT_SYMBOL(csum_ipv6_magic); #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 /* diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c index e2a04324b5c8..633273954f30 100644 --- a/arch/alpha/kernel/bios32.c +++ b/arch/alpha/kernel/bios32.c @@ -31,9 +31,15 @@ #include #include #include +#include #include -#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) @@ -43,161 +49,288 @@ asmlinkage int sys_pciconfig_read() { return -ENOSYS; } asmlinkage int sys_pciconfig_write() { return -ENOSYS; } +void reset_for_srm(void) { } #else /* CONFIG_PCI */ #include #include -#include #include #include #include #include - -#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; @@ -208,12 +341,20 @@ static void disable_dev(struct pci_dev *dev) */ 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... :-\ */ @@ -223,6 +364,19 @@ static void disable_dev(struct pci_dev *dev) 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); @@ -237,7 +391,11 @@ static void disable_dev(struct pci_dev *dev) */ #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; @@ -251,12 +409,20 @@ static void layout_dev(struct pci_dev *dev) */ 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... :-\ */ @@ -315,7 +481,7 @@ static void layout_dev(struct pci_dev *dev) 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", @@ -400,7 +566,7 @@ static void layout_dev(struct pci_dev *dev) 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)); @@ -431,8 +597,8 @@ static void layout_dev(struct pci_dev *dev) 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; @@ -543,24 +709,44 @@ static int layout_bus(struct pci_bus *bus) 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. @@ -575,7 +761,9 @@ pcibios_init(void) * 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; @@ -586,68 +774,29 @@ static inline void enable_ide(long ide_base) 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!! */ } @@ -662,1160 +811,148 @@ printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n", 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)) { @@ -1827,401 +964,37 @@ static inline void sio_fixup(void) } 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 */ diff --git a/arch/alpha/kernel/bios32.h b/arch/alpha/kernel/bios32.h new file mode 100644 index 000000000000..9a3184fe5241 --- /dev/null +++ b/arch/alpha/kernel/bios32.h @@ -0,0 +1,155 @@ +/* + * 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_; }) diff --git a/arch/alpha/kernel/apecs.c b/arch/alpha/kernel/core_apecs.c similarity index 51% rename from arch/alpha/kernel/apecs.c rename to arch/alpha/kernel/core_apecs.c index cc8912aa19c3..d2633bef1d99 100644 --- a/arch/alpha/kernel/apecs.c +++ b/arch/alpha/kernel/core_apecs.c @@ -1,5 +1,7 @@ /* - * Code common to all APECS chips. + * linux/arch/alpha/kernel/core_apecs.c + * + * Code common to all APECS core logic chips. * * Rewritten for Apecs from the lca.c from: * @@ -11,21 +13,24 @@ #include #include #include +#include #include -#include -#include #include +#define __EXTERN_INLINE inline +#include +#include +#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 struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - /* * BIOS32-style PCI interface: */ @@ -38,14 +43,10 @@ extern asmlinkage void wrmces(unsigned long mces); #define vuip volatile unsigned int * -static volatile unsigned int apecs_mcheck_expected = 0; -static volatile unsigned int apecs_mcheck_taken = 0; +volatile unsigned int apecs_mcheck_expected = 0; +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 @@ -88,9 +89,10 @@ unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT; * 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) + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) { unsigned long addr; @@ -121,40 +123,25 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, return 0; } - -static unsigned int conf_read(unsigned long addr, unsigned char type1) +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 + 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: */ + /* 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 access, must set HAE #2. */ if (type1) { haxr2 = *(vuip)APECS_IOC_HAXR2; mb(); @@ -166,10 +153,13 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) apecs_mcheck_expected = 1; apecs_mcheck_taken = 0; mb(); - /* access configuration space: */ - value = *(vuip)addr; - mb(); - mb(); /* magic */ + + /* 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; @@ -187,16 +177,18 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) */ draina(); - /* now look for any errors */ + /* 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 */ + + /* 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: */ + /* Reset error status. */ *(vuip)APECS_IOC_DCSR = stat0; mb(); wrmces(0x7); /* reset machine check */ @@ -204,40 +196,32 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) } #endif - /* if Type1 access, must reset HAE #2 so normal IO space ops work */ + /* 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) +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 */ + unsigned int haxr2 = 0; save_flags(flags); /* avoid getting hit by machine check */ cli(); - /* reset status register to avoid losing errors: */ + /* 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 access, must set HAE #2. */ if (type1) { haxr2 = *(vuip)APECS_IOC_HAXR2; mb(); @@ -247,7 +231,8 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ draina(); apecs_mcheck_expected = 1; mb(); - /* access configuration space: */ + + /* Access configuration space. */ *(vuip)addr = value; mb(); mb(); /* magic */ @@ -263,22 +248,24 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ */ draina(); - /* now look for any errors */ + /* Now look for any errors. */ stat0 = *(vuip)APECS_IOC_DCSR; - if (stat0 & 0xffe0U) { /* is any error bit set? */ - /* if not NDEV, print status */ + + /* 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: */ + /* 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 access, must reset HAE #2 so normal IO space ops work. */ if (type1) { *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; mb(); @@ -286,9 +273,8 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ restore_flags(flags); } - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) +int +apecs_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) { unsigned long addr = APECS_CONF; unsigned long pci_addr; @@ -296,9 +282,8 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, *value = 0xff; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; addr |= (pci_addr << 5) + 0x00; @@ -307,9 +292,8 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, return PCIBIOS_SUCCESSFUL; } - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) +int +apecs_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) { unsigned long addr = APECS_CONF; unsigned long pci_addr; @@ -317,13 +301,10 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, *value = 0xffff; - if (where & 0x1) { + if (where & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; addr |= (pci_addr << 5) + 0x08; @@ -331,195 +312,138 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, return PCIBIOS_SUCCESSFUL; } - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) +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) { + if (where & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; - } + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; - 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) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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; } - -unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end) +void __init +apecs_init_arch(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 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)) + switch (alpha_use_srm_setup) { - 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); + 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 - } - 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 */ + break; + } - *(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; + /* 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; } -#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. + * 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 (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; + *(vuip)APECS_IOC_HAXR2 = 0; mb(); } -int apecs_pci_clr_err(void) +int +apecs_pci_clr_err(void) { apecs_jd = *(vuip)APECS_IOC_DCSR; if (apecs_jd & 0xffe0L) { @@ -534,21 +458,24 @@ int apecs_pci_clr_err(void) return 0; } -void apecs_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) +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_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); + + 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", @@ -563,23 +490,15 @@ void apecs_machine_check(unsigned long vector, 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 */ +#endif /* * 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 + + if (apecs_mcheck_expected + && (mchk_sysdata->epic_dcsr & 0x0c00UL)) { apecs_mcheck_expected = 0; apecs_mcheck_taken = 1; mb(); @@ -591,7 +510,8 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr, DBG(("apecs_machine_check: EXPECTED\n")); } else if (vector == 0x620 || vector == 0x630) { - wrmces(0x1f); /* disable correctable from now on */ + /* Disable correctable from now on. */ + wrmces(0x1f); mb(); draina(); printk("apecs_machine_check: HW correctable (0x%lx)\n", @@ -611,8 +531,8 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr, 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]); + printk(KERN_CRIT " +%lx %lx %lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); } #if 0 /* doesn't work with MILO */ diff --git a/arch/alpha/kernel/cia.c b/arch/alpha/kernel/core_cia.c similarity index 55% rename from arch/alpha/kernel/cia.c rename to arch/alpha/kernel/core_cia.c index 079b4c22545b..9f290bf8029c 100644 --- a/arch/alpha/kernel/cia.c +++ b/arch/alpha/kernel/core_cia.c @@ -1,5 +1,7 @@ /* - * Code common to all CIA chips. + * 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. @@ -10,12 +12,17 @@ #include #include #include +#include #include -#include -#include #include -#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -23,7 +30,6 @@ * handle the system transaction. Another involves timing. Ho hum. */ -extern struct hwrpb_struct *hwrpb; extern asmlinkage void wrmces(unsigned long mces); /* @@ -42,16 +48,16 @@ extern asmlinkage void wrmces(unsigned long mces); * BIOS32-style PCI interface: */ -/* #define DEBUG_MCHECK */ -/* #define DEBUG_CONFIG */ +#define DEBUG_MCHECK 0 +#define DEBUG_CONFIG 0 /* #define DEBUG_DUMP_REGS */ -#ifdef DEBUG_MCHECK +#if DEBUG_MCHECK # define DBGM(args) printk args #else # define DBGM(args) #endif -#ifdef DEBUG_CONFIG +#if DEBUG_CONFIG # define DBGC(args) printk args #else # define DBGC(args) @@ -63,11 +69,6 @@ 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 @@ -110,9 +111,10 @@ unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3; * 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) + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) { unsigned long addr; @@ -123,7 +125,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, if (bus == 0) { int device = device_fn >> 3; - /* type 0 configuration cycle: */ + /* Type 0 configuration cycle. */ if (device > 20) { DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n", @@ -134,7 +136,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, *type1 = 0; addr = (device_fn << 8) | (where); } else { - /* type 1 configuration cycle: */ + /* Type 1 configuration cycle. */ *type1 = 1; addr = (bus << 16) | (device_fn << 8) | (where); } @@ -143,12 +145,12 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, return 0; } - -static unsigned int conf_read(unsigned long addr, unsigned char type1) +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 */ + unsigned int cia_cfg = 0; value = 0xffffffffU; mb(); @@ -158,12 +160,13 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); - /* reset status register to avoid losing errors: */ + /* 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 access, must set CIA CFG. */ if (type1) { cia_cfg = *(vuip)CIA_IOC_CFG; *(vuip)CIA_IOC_CFG = cia_cfg | 1; @@ -176,7 +179,8 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) CIA_mcheck_expected = 1; CIA_mcheck_taken = 0; mb(); - /* access configuration space: */ + + /* Access configuration space. */ value = *(vuip)addr; mb(); mb(); /* magic */ @@ -189,17 +193,17 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) 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. - */ + /* 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 */ + /* 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 */ + + /* 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); } @@ -212,7 +216,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) } #endif - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ if (type1) { *(vuip)CIA_IOC_CFG = cia_cfg & ~1; mb(); @@ -224,23 +228,23 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) return value; } - -static void conf_write(unsigned long addr, unsigned int value, - unsigned char type1) +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 */ + unsigned int cia_cfg = 0; save_flags(flags); /* avoid getting hit by machine check */ cli(); - /* reset status register to avoid losing errors: */ + /* 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 access, must set CIA CFG. */ if (type1) { cia_cfg = *(vuip)CIA_IOC_CFG; *(vuip)CIA_IOC_CFG = cia_cfg | 1; @@ -251,7 +255,8 @@ static void conf_write(unsigned long addr, unsigned int value, draina(); CIA_mcheck_expected = 1; mb(); - /* access configuration space: */ + + /* Access configuration space. */ *(vuip)addr = value; mb(); mb(); /* magic */ @@ -260,22 +265,22 @@ static void conf_write(unsigned long addr, unsigned int value, 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. - */ + /* 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? */ + + /* 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: */ + /* Reset error status. */ *(vuip)CIA_IOC_CIA_ERR = stat0; mb(); wrmces(0x7); /* reset machine check */ @@ -283,7 +288,7 @@ static void conf_write(unsigned long addr, unsigned int value, } #endif - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ if (type1) { *(vuip)CIA_IOC_CFG = cia_cfg & ~1; mb(); @@ -293,9 +298,8 @@ static void conf_write(unsigned long addr, unsigned int value, restore_flags(flags); } - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) +int +cia_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) { unsigned long addr = CIA_CONF; unsigned long pci_addr; @@ -303,20 +307,16 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, *value = 0xff; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) +int +cia_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) { unsigned long addr = CIA_CONF; unsigned long pci_addr; @@ -324,91 +324,85 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, *value = 0xffff; - if (where & 0x1) { + if (where & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) +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) { + if (where & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; - } + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; - 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) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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; } - -unsigned long cia_init(unsigned long mem_start, unsigned long mem_end) +void __init +cia_init_arch(unsigned long *mem_start, unsigned long *mem_end) { unsigned int cia_tmp; @@ -416,49 +410,49 @@ unsigned long cia_init(unsigned long mem_start, unsigned long mem_end) { unsigned int temp; temp = *(vuip)CIA_IOC_CIA_REV; mb(); - printk("CIA_init: CIA_REV was 0x%x\n", temp); + 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); + 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); + printk("cia_init: CIA_CTRL was 0x%x\n", temp); temp = *(vuip)0xfffffc8740000140UL; mb(); - printk("CIA_init: CIA_CTRL1 was 0x%x\n", temp); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + printk("cia_init: W3_BASE was 0x%x\n", temp); } #endif /* DEBUG_DUMP_REGS */ @@ -471,152 +465,147 @@ unsigned long cia_init(unsigned long mem_start, unsigned long mem_end) mb(); cia_tmp = *(vuip)CIA_IOC_CIA_CTRL; - cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */ + 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)) + switch (alpha_use_srm_setup) { - 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; + 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); + 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; + 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); + 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; + 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); + 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; + 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); + 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; - } + break; + } - /* - * 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; + /* 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... + * 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(); - } - } + *((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 */ + + /* + * 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. */ } - - return mem_start; } -int cia_pci_clr_err(void) +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)); @@ -625,11 +614,12 @@ int cia_pci_clr_err(void) return 0; } -void cia_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) +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_procdata *mchk_procdata; struct el_CIA_sysdata_mcheck *mchk_sysdata; unsigned long * ptr; const char * reason; @@ -637,8 +627,10 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, long i; mchk_header = (struct el_common *)la_ptr; - mchk_procdata = (struct el_procdata *) + + 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); @@ -651,7 +643,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, CIA_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear)); -#ifdef DEBUG_MCHECK +#if DEBUG_MCHECK { unsigned long *ptr; int i; @@ -686,7 +678,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, 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_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; @@ -694,7 +686,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, 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): */ + /* 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; @@ -720,16 +712,16 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, wrmces(rdmces()); /* reset machine check pending flag */ mb(); - printk(KERN_CRIT " CIA machine check: %s%s\n", + 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: */ + /* 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", + printk(KERN_CRIT " +%8lx %016lx %016lx\n", i*sizeof(long), ptr[i], ptr[i+1]); } } diff --git a/arch/alpha/kernel/lca.c b/arch/alpha/kernel/core_lca.c similarity index 71% rename from arch/alpha/kernel/lca.c rename to arch/alpha/kernel/core_lca.c index 7e9b03c34817..fe1e7795229b 100644 --- a/arch/alpha/kernel/lca.c +++ b/arch/alpha/kernel/core_lca.c @@ -1,5 +1,7 @@ /* - * Code common to all LCA chips. + * 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 @@ -9,19 +11,24 @@ #include #include #include +#include +#include #include #include -#include #include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.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). @@ -38,6 +45,7 @@ #define MCHK_K_DCPERR 0x0092 #define MCHK_K_ICPERR 0x0094 + /* * Platform-specific machine-check reasons: */ @@ -45,10 +53,6 @@ #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 @@ -91,8 +95,9 @@ unsigned int LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT; * 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) + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr) { unsigned long addr; @@ -100,7 +105,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, int device = device_fn >> 3; int func = device_fn & 0x7; - /* type 0 configuration cycle: */ + /* Type 0 configuration cycle. */ if (device > 12) { return -1; @@ -109,7 +114,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, *(vulp)LCA_IOC_CONF = 0; addr = (1 << (11 + device)) | (func << 8) | where; } else { - /* type 1 configuration cycle: */ + /* Type 1 configuration cycle. */ *(vulp)LCA_IOC_CONF = 1; addr = (bus << 16) | (device_fn << 8) | where; } @@ -117,8 +122,8 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, return 0; } - -static unsigned int conf_read(unsigned long addr) +static unsigned int +conf_read(unsigned long addr) { unsigned long flags, code, stat0; unsigned int value; @@ -126,13 +131,12 @@ static unsigned int conf_read(unsigned long addr) save_flags(flags); cli(); - /* reset status register to avoid loosing errors: */ + /* Reset status register to avoid loosing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; *(vulp)LCA_IOC_STAT0 = stat0; mb(); - /* access configuration space: */ - + /* Access configuration space. */ value = *(vuip)addr; draina(); @@ -144,10 +148,12 @@ static unsigned int conf_read(unsigned long addr) printk("lca.c:conf_read: got stat0=%lx\n", stat0); } - /* reset error status: */ + /* Reset error status. */ *(vulp)LCA_IOC_STAT0 = stat0; mb(); - wrmces(0x7); /* reset machine check */ + + /* Reset machine check. */ + wrmces(0x7); value = 0xffffffff; } @@ -155,21 +161,20 @@ static unsigned int conf_read(unsigned long addr) return value; } - -static void conf_write(unsigned long addr, unsigned int 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: */ + /* Reset status register to avoid loosing errors. */ stat0 = *(vulp)LCA_IOC_STAT0; *(vulp)LCA_IOC_STAT0 = stat0; mb(); - /* access configuration space: */ - + /* Access configuration space. */ *(vuip)addr = value; draina(); @@ -181,163 +186,170 @@ static void conf_write(unsigned long addr, unsigned int value) printk("lca.c:conf_write: got stat0=%lx\n", stat0); } - /* reset error status: */ + /* Reset error status. */ *(vulp)LCA_IOC_STAT0 = stat0; mb(); - wrmces(0x7); /* reset machine check */ + + /* Reset machine check. */ + wrmces(0x7); } restore_flags(flags); } - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) +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) { + if (where & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; - } - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) +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) { + if (where & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; - } - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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; } - -unsigned long lca_init(unsigned long mem_start, unsigned long mem_end) +void __init +lca_init_arch(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)) + switch (alpha_use_srm_setup) { - 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); + 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 - } - 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; + 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); + 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; + break; + } - *(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; + /* 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; } /* @@ -346,10 +358,8 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end) * 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 @@ -374,12 +384,12 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end) #define IOC_LOST ( 1<<5) #define IOC_P_NBR ((__u32) ~((1<<13) - 1)) - -void mem_error (unsigned long esr, unsigned long ear) +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_CEE) ? "Correctable" : + (esr & ESR_UEE) ? "Uncorrectable" : "A"), (esr & ESR_WRE) ? "write" : "read", (esr & ESR_SOR) ? "memory" : "b-cache", (unsigned) (ear & 0x1ffffff8)); @@ -397,8 +407,8 @@ void mem_error (unsigned long esr, unsigned long ear) } } - -void ioc_error (__u32 stat0, __u32 stat1) +static void +ioc_error (__u32 stat0, __u32 stat1) { static const char * const pci_cmd[] = { "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write", @@ -428,9 +438,9 @@ void ioc_error (__u32 stat0, __u32 stat1) } } - -void lca_machine_check (unsigned long vector, unsigned long la, - struct pt_regs *regs) +void +lca_machine_check (unsigned long vector, unsigned long la, + struct pt_regs *regs) { unsigned long * ptr; const char * reason; @@ -441,6 +451,7 @@ void lca_machine_check (unsigned long vector, unsigned long la, 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 @@ -505,7 +516,7 @@ void lca_machine_check (unsigned long vector, unsigned long la, printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size); } - /* dump the logout area to give all info: */ + /* Dump the logout area to give all info. */ ptr = (unsigned long *) la; for (i = 0; i < el.c->size / sizeof(long); i += 2) { @@ -524,11 +535,11 @@ lca_clock_print(void) { long pmr_reg; - pmr_reg = READ_PMR; + pmr_reg = LCA_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("\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", @@ -541,8 +552,8 @@ lca_get_clock(void) { long pmr_reg; - pmr_reg = READ_PMR; - return(GET_PRIMARY(pmr_reg)); + pmr_reg = LCA_READ_PMR; + return(LCA_GET_PRIMARY(pmr_reg)); } @@ -551,9 +562,9 @@ lca_clock_fiddle(int divisor) { long pmr_reg; - pmr_reg = READ_PMR; - SET_PRIMARY_CLOCK(pmr_reg, divisor); + pmr_reg = LCA_READ_PMR; + LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor); /* lca_norm_clock = divisor; */ - WRITE_PMR(pmr_reg); + LCA_WRITE_PMR(pmr_reg); mb(); } diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c new file mode 100644 index 000000000000..b1948610b6c2 --- /dev/null +++ b/arch/alpha/kernel/core_mcpcia.c @@ -0,0 +1,969 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#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); +} diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c new file mode 100644 index 000000000000..ab49de09615d --- /dev/null +++ b/arch/alpha/kernel/core_pyxis.c @@ -0,0 +1,634 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#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 +} diff --git a/arch/alpha/kernel/t2.c b/arch/alpha/kernel/core_t2.c similarity index 61% rename from arch/alpha/kernel/t2.c rename to arch/alpha/kernel/core_t2.c index 2430aae2202a..13adb7bdfe48 100644 --- a/arch/alpha/kernel/t2.c +++ b/arch/alpha/kernel/core_t2.c @@ -1,5 +1,7 @@ /* - * Code common to all T2 chips. + * 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. @@ -7,17 +9,22 @@ * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com) * */ -#include #include +#include #include #include #include +#include +#include #include + +#define __EXTERN_INLINE #include -#include -#include -#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -25,9 +32,6 @@ * 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). @@ -56,17 +60,9 @@ extern asmlinkage void wrmces(unsigned long mces); # 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 @@ -109,9 +105,10 @@ unsigned long t2_sm_base; * 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) + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) { unsigned long addr; @@ -122,7 +119,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, if (bus == 0) { int device = device_fn >> 3; - /* type 0 configuration cycle: */ + /* Type 0 configuration cycle. */ if (device > 8) { DBG(("mk_conf_addr: device (%d)>20, returning -1\n", @@ -133,7 +130,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, *type1 = 0; addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where); } else { - /* type 1 configuration cycle: */ + /* Type 1 configuration cycle. */ *type1 = 1; addr = (bus << 16) | (device_fn << 8) | (where); } @@ -142,12 +139,12 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn, return 0; } - -static unsigned int conf_read(unsigned long addr, unsigned char type1) +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 */ + unsigned long t2_cfg = 0; cpu = smp_processor_id(); @@ -157,13 +154,14 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); #if 0 - /* reset status register to avoid losing errors: */ + /* 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 access, must set T2 CFG. */ if (type1) { t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg; @@ -176,10 +174,12 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) T2_mcheck_expected[cpu] = 1; T2_mcheck_taken[cpu] = 0; mb(); - /* access configuration space: */ + + /* Access configuration space. */ value = *(vuip)addr; mb(); mb(); /* magic */ + if (T2_mcheck_taken[cpu]) { T2_mcheck_taken[cpu] = 0; value = 0xffffffffU; @@ -188,7 +188,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) T2_mcheck_expected[cpu] = 0; mb(); - /* if Type1 access, must reset T2 CFG so normal IO space ops work */ + /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ if (type1) { *(vulp)T2_HAE_3 = t2_cfg; mb(); @@ -199,13 +199,12 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1) return value; } - -static void conf_write(unsigned long addr, unsigned int value, - unsigned char type1) +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 */ + unsigned long t2_cfg = 0; cpu = smp_processor_id(); @@ -213,13 +212,14 @@ static void conf_write(unsigned long addr, unsigned int value, cli(); #if 0 - /* reset status register to avoid losing errors: */ + /* 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 access, must set T2 CFG. */ if (type1) { t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL; @@ -231,14 +231,16 @@ static void conf_write(unsigned long addr, unsigned int value, T2_mcheck_expected[cpu] = 1; mb(); - /* access configuration space: */ + + /* 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 access, must reset T2 CFG so normal IO space ops work. */ if (type1) { *(vulp)T2_HAE_3 = t2_cfg; mb(); @@ -248,121 +250,109 @@ static void conf_write(unsigned long addr, unsigned int value, } -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) +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) { + if (where & 0x1) return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) +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) { + if (where & 0x3) return PCIBIOS_BAD_REGISTER_NUMBER; - } + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; - 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) +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) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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 pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) +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 (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } + 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; } - -unsigned long t2_init(unsigned long mem_start, unsigned long mem_end) +void __init +t2_init_arch(unsigned long *mem_start, unsigned long *mem_end) { unsigned long t2_err; unsigned int i; @@ -394,138 +384,129 @@ unsigned long t2_init(unsigned long mem_start, unsigned long mem_end) *(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)) + switch (alpha_use_srm_setup) { - T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL; - T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL; - T2_DMA_WIN_SIZE += 0x00100000UL; -/* DISABLE window 2!! ?? */ + 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); + 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!! ?? */ + 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); + 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; - } + break; + } - /* - * 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; + /* 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; } /* - * 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... + * 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. */ - { - 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 (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 */ + *(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) +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")); - sable_cpu_regs[cpu]->sic &= ~SIC_SEIC; + cpu_regs->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; + 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; @@ -535,8 +516,9 @@ int t2_clear_errors(void) return 0; } -void t2_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) +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; @@ -556,9 +538,9 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr, mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset)); mchk_sysdata = (struct el_t2_sysdata_mcheck *) - (la_ptr + mchk_header->elfl_sysoffset); + (la_ptr + mchk_header->elfl_sysoffset); mchk_procdata = (struct el_t2_procdata_mcheck *) - (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32); + (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, @@ -607,7 +589,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr, 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): */ + /* 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; @@ -636,7 +618,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr, printk(KERN_CRIT " T2 machine check: %s%s\n", reason, mchk_header->elfl_retry ? " (retryable)" : ""); - /* dump the logout area to give all info: */ + /* 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) { diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c new file mode 100644 index 000000000000..382a97647ca0 --- /dev/null +++ b/arch/alpha/kernel/core_tsunami.c @@ -0,0 +1,446 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#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 +} diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index eb13590fc22a..79b0d818cd60 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -15,7 +15,7 @@ #define osf_vfork sys_fork /* - * These offsets must match with "struct hae" in io.h: + * These offsets must match with alpha_mv in . */ #define HAE_CACHE 0 #define HAE_REG 8 @@ -109,7 +109,7 @@ 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); \ @@ -130,7 +130,7 @@ 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); \ @@ -1135,7 +1135,7 @@ sys_call_table: .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 diff --git a/arch/alpha/kernel/es1888.c b/arch/alpha/kernel/es1888.c new file mode 100644 index 000000000000..10115ac8dc62 --- /dev/null +++ b/arch/alpha/kernel/es1888.c @@ -0,0 +1,47 @@ +/* + * linux/arch/alpha/kernel/es1888.c + * + * Init the built-in ES1888 sound chip (SB16 compatible) + */ + +#include +#include +#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 */ +} diff --git a/arch/alpha/kernel/fpreg.c b/arch/alpha/kernel/fpreg.c index 502144058d1c..6da94c0cbb61 100644 --- a/arch/alpha/kernel/fpreg.c +++ b/arch/alpha/kernel/fpreg.c @@ -4,62 +4,58 @@ * (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 @@ -98,7 +94,5 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val) case 29: LDT(29, val); break; case 30: LDT(30, val); break; case 31: LDT(31, val); break; - default: - break; } } diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S index 48ad8ff82efd..92e11a82ec0b 100644 --- a/arch/alpha/kernel/head.S +++ b/arch/alpha/kernel/head.S @@ -7,7 +7,6 @@ * the kernel global pointer and jump to the kernel entry-point. */ -#define __ASSEMBLY__ #include #define halt call_pal PAL_halt diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 9470ee69a90f..0fee440e1eee 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -25,14 +25,17 @@ #include #include #include -#include +#include + +#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 @@ -45,497 +48,169 @@ extern void handle_ipi(struct pt_regs *); # 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; @@ -545,22 +220,21 @@ int check_irq(unsigned int irq) 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) { @@ -580,11 +254,11 @@ int request_irq(unsigned int irq, 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; @@ -602,18 +276,19 @@ int request_irq(unsigned int irq, *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; } @@ -629,7 +304,7 @@ void free_irq(unsigned int irq, void *dev_id) 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; @@ -637,14 +312,29 @@ void free_irq(unsigned int irq, void *dev_id) 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. */ @@ -666,10 +356,17 @@ static unsigned long previous_irqholder = NO_PROC_ID; #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]; @@ -706,10 +403,15 @@ static inline void wait_on_irq(int cpu, unsigned long where) #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; @@ -745,7 +447,8 @@ static inline void get_irqlock(int cpu, unsigned long where) previous_irqholder = where; } -void __global_cli(void) +void +__global_cli(void) { int cpu = smp_processor_id(); unsigned long where; @@ -754,27 +457,30 @@ void __global_cli(void) __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(); @@ -793,12 +499,17 @@ void __global_restore_flags(unsigned long flags) #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); @@ -813,10 +524,10 @@ void irq_enter(int cpu, int irq) 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," @@ -838,13 +549,15 @@ void irq_enter(int cpu, int irq) } } -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; @@ -873,7 +586,8 @@ static void show(char * str) #define MAXCOUNT 100000000 -static inline void wait_on_bh(void) +static inline void +wait_on_bh(void) { int count = MAXCOUNT; do { @@ -893,7 +607,8 @@ static inline void wait_on_bh(void) * 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(); @@ -904,7 +619,8 @@ void synchronize_bh(void) } /* 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]; @@ -918,26 +634,35 @@ void synchronize_irq(void) } } -#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 @@ -951,33 +676,16 @@ static void unexpected_irq(int irq, struct pt_regs * regs) #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; @@ -992,8 +700,10 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs) * 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); @@ -1001,622 +711,28 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs) 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; } @@ -1634,8 +750,8 @@ unsigned long probe_irq_on(void) 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; } /* @@ -1643,11 +759,13 @@ unsigned long probe_irq_on(void) * 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); @@ -1656,42 +774,10 @@ int probe_irq_off(unsigned long 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, @@ -1701,56 +787,20 @@ 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"); @@ -1761,226 +811,9 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr, 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(); } diff --git a/arch/alpha/kernel/irq.h b/arch/alpha/kernel/irq.h new file mode 100644 index 000000000000..08db28ec5856 --- /dev/null +++ b/arch/alpha/kernel/irq.h @@ -0,0 +1,27 @@ +/* + * 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); diff --git a/arch/alpha/kernel/machvec.h b/arch/alpha/kernel/machvec.h new file mode 100644 index 000000000000..5aa2ead60383 --- /dev/null +++ b/arch/alpha/kernel/machvec.h @@ -0,0 +1,136 @@ +/* + * 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 diff --git a/arch/alpha/kernel/mcpcia.c b/arch/alpha/kernel/mcpcia.c deleted file mode 100644 index e88526fb8508..000000000000 --- a/arch/alpha/kernel/mcpcia.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Code common to all MCbus-PCI adaptor chipsets - * - * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * 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 */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index efeafe411ed9..b3e919500a76 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -47,7 +47,7 @@ extern struct file_operations *get_chrfops(unsigned int); 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); @@ -542,7 +542,7 @@ asmlinkage int osf_umount(char *path, int flag) int ret; lock_kernel(); - ret = sys_umount(path); + ret = sys_umount(path,flag); unlock_kernel(); return ret; } diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index ba3c41563c2e..697572e7ae67 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_RTC #include @@ -41,6 +42,9 @@ #include #include +#include "proto.h" +#include "bios32.h" + /* * Initial task structure. Make this a per-architecture thing, * because different architectures tend to have different @@ -62,20 +66,20 @@ union task_union init_task_union __attribute__((section("init_task"))) /* * 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; @@ -90,7 +94,8 @@ int cpu_idle(void *unused) } } -asmlinkage int sys_idle(void) +asmlinkage int +sys_idle(void) { if(current->pid != 0) return -EPERM; @@ -101,7 +106,8 @@ asmlinkage int sys_idle(void) #else /* __SMP__ */ -asmlinkage int sys_idle(void) +asmlinkage int +sys_idle(void) { int ret = -EPERM; @@ -122,90 +128,101 @@ out: } #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) diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h new file mode 100644 index 000000000000..f55a0edba2b5 --- /dev/null +++ b/arch/alpha/kernel/proto.h @@ -0,0 +1,131 @@ +/* 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); diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index d91ede2995a8..384f534af607 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -281,10 +281,8 @@ static int read_long(struct task_struct * tsk, unsigned long addr, 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; diff --git a/arch/alpha/kernel/pyxis.c b/arch/alpha/kernel/pyxis.c deleted file mode 100644 index 9db4fe4d7851..000000000000 --- a/arch/alpha/kernel/pyxis.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - * Code common to all PYXIS chips. - * - * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include /* CONFIG_ALPHA_RUFFIAN. */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* 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 */ diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index f0683b1c10bf..419fb47de0be 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -5,10 +5,9 @@ */ /* - * bootup setup stuff.. + * Bootup setup stuff. */ -#include #include #include #include @@ -24,6 +23,9 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_RTC #include @@ -36,8 +38,8 @@ #include #include -extern void setup_smp(void); -extern char *smp_info(void); + +#include "proto.h" #if 1 # define DBG_SRM(args) printk args @@ -45,19 +47,23 @@ extern char *smp_info(void); # 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 @@ -68,161 +74,241 @@ unsigned char aux_device_present = 0xaa; #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; @@ -230,81 +316,284 @@ void setup_arch(char **cmdline_p, 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 */ @@ -353,9 +642,47 @@ get_sysnames(long type, long variation, 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))); + } } /* @@ -363,20 +690,21 @@ get_sysnames(long type, long variation, */ 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); @@ -387,30 +715,25 @@ int get_cpuinfo(char *buffer) 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, @@ -424,9 +747,11 @@ int get_cpuinfo(char *buffer) 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 - ); } diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 7226ed83c769..53175a0f11f9 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -24,6 +24,8 @@ #define __KERNEL_SYSCALLS__ #include +#include "proto.h" + struct ipi_msg_flush_tb_struct ipi_msg_flush_tb; struct cpuinfo_alpha cpu_data[NR_CPUS]; @@ -735,15 +737,11 @@ send_ipi_message(long to_whom, enum ipi_message_type operation) } } -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() */ diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c new file mode 100644 index 000000000000..9b9dd34cf3a6 --- /dev/null +++ b/arch/alpha/kernel/sys_alcor.c @@ -0,0 +1,263 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c new file mode 100644 index 000000000000..273d53c0b413 --- /dev/null +++ b/arch/alpha/kernel/sys_cabriolet.c @@ -0,0 +1,395 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c new file mode 100644 index 000000000000..e110891befc4 --- /dev/null +++ b/arch/alpha/kernel/sys_dp264.c @@ -0,0 +1,231 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c new file mode 100644 index 000000000000..bffd119f33a3 --- /dev/null +++ b/arch/alpha/kernel/sys_eb64p.c @@ -0,0 +1,206 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c new file mode 100644 index 000000000000..8406661d738a --- /dev/null +++ b/arch/alpha/kernel/sys_jensen.c @@ -0,0 +1,146 @@ +/* + * linux/arch/alpha/kernel/sys_jensen.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the Jensen. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c new file mode 100644 index 000000000000..71ec1b2ccf4e --- /dev/null +++ b/arch/alpha/kernel/sys_miata.c @@ -0,0 +1,307 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c new file mode 100644 index 000000000000..92af5d372e80 --- /dev/null +++ b/arch/alpha/kernel/sys_mikasa.c @@ -0,0 +1,297 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c new file mode 100644 index 000000000000..c8901ae2f1e6 --- /dev/null +++ b/arch/alpha/kernel/sys_noritake.c @@ -0,0 +1,301 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c new file mode 100644 index 000000000000..0885a232acc8 --- /dev/null +++ b/arch/alpha/kernel/sys_rawhide.c @@ -0,0 +1,195 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c new file mode 100644 index 000000000000..9d32bcb15d9b --- /dev/null +++ b/arch/alpha/kernel/sys_ruffian.c @@ -0,0 +1,267 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c new file mode 100644 index 000000000000..42a1f9c48cfd --- /dev/null +++ b/arch/alpha/kernel/sys_sable.c @@ -0,0 +1,297 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c new file mode 100644 index 000000000000..dfd6adaa72e1 --- /dev/null +++ b/arch/alpha/kernel/sys_sio.c @@ -0,0 +1,470 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c new file mode 100644 index 000000000000..1219b9626da3 --- /dev/null +++ b/arch/alpha/kernel/sys_sx164.c @@ -0,0 +1,217 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c new file mode 100644 index 000000000000..326fd6409303 --- /dev/null +++ b/arch/alpha/kernel/sys_takara.c @@ -0,0 +1,165 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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) diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index d6c1a7e4549d..c2fc4c8e6927 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -20,8 +20,10 @@ #include #include +#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); @@ -51,7 +53,8 @@ static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) 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; @@ -65,7 +68,8 @@ static void dik_show_code(unsigned int *pc) printk("\n"); } -static void dik_show_trace(unsigned long *sp) +static void +dik_show_trace(unsigned long *sp) { long i = 0; printk("Trace:"); @@ -86,8 +90,8 @@ static void dik_show_trace(unsigned long *sp) 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; @@ -106,21 +110,20 @@ void die_if_kernel(char * str, struct pt_regs *regs, long err, } #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)) { /* @@ -133,8 +136,10 @@ asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask, } 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(); @@ -202,7 +207,6 @@ asmlinkage void do_entIF(unsigned long type, unsigned long a1, 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: */ @@ -255,9 +259,10 @@ struct unaligned_stat { #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; @@ -497,7 +502,8 @@ got_exception: * 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; @@ -524,7 +530,8 @@ static inline unsigned long s_mem_to_reg (unsigned long s_mem) * 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); } @@ -571,12 +578,10 @@ static int unauser_reg_offsets[32] = { #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; @@ -868,10 +873,10 @@ give_sigbus: /* * 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. */ @@ -879,17 +884,11 @@ asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1, 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); diff --git a/arch/alpha/kernel/tsunami.c b/arch/alpha/kernel/tsunami.c deleted file mode 100644 index f351632b843a..000000000000 --- a/arch/alpha/kernel/tsunami.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Code common to all TSUNAMI chips. - * - * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * 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 */ diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index 7c1e37bac683..4dd7d591d770 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -7,7 +7,7 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \ 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) diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c index 7c99fe5aea18..50cc1fe05cee 100644 --- a/arch/alpha/lib/io.c +++ b/arch/alpha/lib/io.c @@ -6,23 +6,6 @@ #include #include -/* - * 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); @@ -470,47 +453,57 @@ void _memcpy_toio(unsigned long to, void * from, long count) /* * "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++; } } diff --git a/arch/alpha/lib/strcasecmp.c b/arch/alpha/lib/strcasecmp.c new file mode 100644 index 000000000000..4e57a216feaf --- /dev/null +++ b/arch/alpha/lib/strcasecmp.c @@ -0,0 +1,26 @@ +/* + * linux/arch/alpha/lib/strcasecmp.c + */ + +#include + + +/* 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; +} diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c index b3c10887b4ca..97f4bc3267f2 100644 --- a/arch/alpha/math-emu/fp-emul.c +++ b/arch/alpha/math-emu/fp-emul.c @@ -61,23 +61,33 @@ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); 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 */ @@ -96,6 +106,8 @@ alpha_fp_emul (unsigned long pc) 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; @@ -105,8 +117,8 @@ alpha_fp_emul (unsigned long pc) va = alpha_read_fp_reg(fa); vb = alpha_read_fp_reg(fb); - fpcr = rdfpcr(); + /* * Try the operation in software. First, obtain the rounding * mode... @@ -213,8 +225,10 @@ alpha_fp_emul (unsigned long pc) 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: @@ -237,8 +251,10 @@ alpha_fp_emul (unsigned long pc) 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; + } } /* @@ -247,6 +263,8 @@ alpha_fp_emul (unsigned long pc) * result: */ alpha_write_fp_reg(fc, vc); + + MOD_DEC_USE_COUNT; return 1; } diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 647456833aa9..f2d5cc763534 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -4,23 +4,31 @@ * Copyright (C) 1995 Linus Torvalds */ -#include #include -#include #include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include +#include +#include #include #include #include #include #include -#include #include #include #include #include -#include -#include + +extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); + #ifdef __SMP__ unsigned long last_asn[NR_CPUS] = { /* gag */ @@ -61,21 +69,26 @@ 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, @@ -99,12 +112,13 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); */ /* 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; diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 3e1437cc12dc..85b1e3e07d20 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -32,19 +32,22 @@ struct thread_struct * original_pcb_ptr; 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; @@ -66,7 +69,8 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) 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; @@ -117,22 +121,25 @@ int do_check_pgt_cache(int low, int high) * 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(); @@ -149,12 +156,12 @@ void show_mem(void) 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(); @@ -163,29 +170,20 @@ void show_mem(void) 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; @@ -242,7 +240,8 @@ printk("OKSP 0x%lx OPTBR 0x%lx\n", * 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; @@ -260,7 +259,8 @@ printk("paging_init_secondary: KSP 0x%lx PTBR 0x%lx\n", } #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; @@ -291,7 +291,8 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) return; } -void free_initmem (void) +void +free_initmem (void) { extern char __init_begin, __init_end; unsigned long addr; @@ -306,7 +307,8 @@ void free_initmem (void) (&__init_end - &__init_begin) >> 10); } -void si_meminfo(struct sysinfo *val) +void +si_meminfo(struct sysinfo *val) { int i; diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 58cc0d38b528..b67cd20d68a9 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -396,7 +396,7 @@ ENTRY(sys_call_table) .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 */ @@ -426,7 +426,7 @@ ENTRY(sys_call_table) .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 */ diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 46fa4ad701c1..0697306a70d2 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -241,9 +241,6 @@ is386: pushl %ecx # restore original EFLAGS #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: diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 330a15982920..84eaf4962d7e 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -36,6 +36,7 @@ #include #include #include +#include #include /* @@ -81,12 +82,10 @@ extern int rd_image_start; /* starting block # of image */ 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 @@ -255,6 +254,27 @@ __initfunc(static int amd_model(struct cpuinfo_x86 *c)) 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. */ diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index b45bf2ec90d2..8116648a3c5e 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -1101,7 +1101,6 @@ __initfunc(void device_setup(void)) extern int soc_probe(void); #endif struct gendisk *p; - int nr=0; #ifdef CONFIG_PARPORT parport_init(); @@ -1123,10 +1122,9 @@ __initfunc(void device_setup(void)) 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(); @@ -1138,3 +1136,25 @@ __initfunc(void device_setup(void)) 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 diff --git a/drivers/block/loop.c b/drivers/block/loop.c index af64cb00873a..268c9187aa3e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -6,14 +6,13 @@ * 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 - 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 */ @@ -427,7 +426,11 @@ static int loop_set_fd(struct loop_device *lo, kdev_t dev, unsigned int arg) 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) diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c index 2b0678849679..a502fedf6798 100644 --- a/drivers/block/trm290.c +++ b/drivers/block/trm290.c @@ -249,7 +249,7 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif)) 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 { /* diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c index 8ed9e9643043..e9e964c4308d 100644 --- a/drivers/char/apm_bios.c +++ b/drivers/char/apm_bios.c @@ -515,6 +515,8 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) 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) { @@ -532,6 +534,7 @@ static int apm_get_battery_status(u_short which, return (error >> 8); return APM_SUCCESS; } +#endif static inline int apm_engage_power_management(u_short device) { diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index c7bae0b443f2..8bb3f203efd2 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -156,6 +156,7 @@ static void * rvmalloc(unsigned long size) 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) { @@ -642,7 +643,16 @@ int palette2fmt[] = { 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) @@ -1044,13 +1054,18 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) */ 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); @@ -1561,6 +1576,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -1927,6 +1943,7 @@ static struct video_device bttv_template= bttv_close, bttv_read, bttv_write, + NULL, /* poll */ bttv_ioctl, bttv_mmap, bttv_init_done, @@ -1980,6 +1997,20 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count, 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); @@ -2017,6 +2048,7 @@ static struct video_device vbi_template= vbi_close, vbi_read, bttv_write, + vbi_poll, vbi_ioctl, NULL, /* no mmap yet */ bttv_init_done, @@ -2113,6 +2145,7 @@ static struct video_device radio_template= 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 */ @@ -2176,7 +2209,7 @@ static int find_vga(void) 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; } @@ -2196,40 +2229,40 @@ static int find_vga(void) 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) @@ -2548,6 +2581,8 @@ static int init_bt848(int i) 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); diff --git a/drivers/char/bw-qcam.c b/drivers/char/bw-qcam.c index 160c9945b560..48de68db3494 100644 --- a/drivers/char/bw-qcam.c +++ b/drivers/char/bw-qcam.c @@ -842,6 +842,7 @@ static struct video_device qcam_template= qcam_close, qcam_read, qcam_write, + NULL, qcam_ioctl, NULL, qcam_init_done, diff --git a/drivers/char/c-qcam.c b/drivers/char/c-qcam.c index 46e2b88bab9c..e6d4c16b5efe 100644 --- a/drivers/char/c-qcam.c +++ b/drivers/char/c-qcam.c @@ -646,6 +646,7 @@ static struct video_device qcam_template= qcam_close, qcam_read, qcam_write, + NULL, qcam_ioctl, NULL, qcam_init_done, diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 81833b821224..c05659fd2f96 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -4949,7 +4949,7 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, 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", diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index cf16d9cf3e3e..65d2f77477f7 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -11,8 +11,8 @@ * 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 @@ -590,6 +590,7 @@ unsigned char handle_diacr(unsigned char ch) if (ch == ' ' || ch == d) return d; + put_queue(d); return ch; } diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 4e49b9f05213..1036f104629b 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -564,7 +564,7 @@ static int lp_open(struct inode * inode, struct file * file) 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; diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c index 73c20a16b42e..18cce49dd474 100644 --- a/drivers/char/msp3400.c +++ b/drivers/char/msp3400.c @@ -58,7 +58,7 @@ #endif -int debug = 0; /* insmod parameter */ +static int debug = 0; /* insmod parameter */ struct msp3400c { struct i2c_bus *bus; @@ -542,7 +542,8 @@ static int msp3400c_thread(void *data) 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; diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c index 5910de6b4114..ad84a09d34a6 100644 --- a/drivers/char/pc_keyb.c +++ b/drivers/char/pc_keyb.c @@ -50,7 +50,7 @@ unsigned char pckbd_sysrq_xlate[128] = */ /* - * 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] */ diff --git a/drivers/char/pms.c b/drivers/char/pms.c index 5c4f3de48348..81c8fbb79ed9 100644 --- a/drivers/char/pms.c +++ b/drivers/char/pms.c @@ -893,6 +893,7 @@ struct video_device pms_template= pms_close, pms_read, pms_write, + NULL, /* FIXME - we can use POLL on this board with the irq */ pms_ioctl, NULL, pms_init_done, diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 3c49647de438..4aaa67579cb4 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -7,6 +7,7 @@ * -- C. Scott Ananian , 14-Jan-1998 */ +#include #include /* For EXPORT_SYMBOL */ #include diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c index ed1cced0236a..014def0c49cc 100644 --- a/drivers/char/radio-aimslab.c +++ b/drivers/char/radio-aimslab.c @@ -155,7 +155,11 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq) /* 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 */ @@ -308,6 +312,7 @@ static struct video_device rtrack_radio= rt_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* No poll */ rt_ioctl, NULL, NULL diff --git a/drivers/char/radio-aztech.c b/drivers/char/radio-aztech.c index e883c712a7b9..aaeaa726558c 100644 --- a/drivers/char/radio-aztech.c +++ b/drivers/char/radio-aztech.c @@ -113,7 +113,8 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency) { 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; @@ -269,6 +270,7 @@ static struct video_device aztech_radio= az_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* No poll */ az_ioctl, NULL, NULL diff --git a/drivers/char/radio-rtrack2.c b/drivers/char/radio-rtrack2.c new file mode 100644 index 000000000000..7daeb4e0167d --- /dev/null +++ b/drivers/char/radio-rtrack2.c @@ -0,0 +1,272 @@ +/* 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 + * Various bugfixes and enhancements by Russell Kroll + * + * TODO: Allow for more than one of these foolish entities :-) + * + */ + +#include /* Modules */ +#include /* Initdata */ +#include /* check_region, request_region */ +#include /* udelay */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include /* kernel radio structs */ +#include /* 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: +*/ diff --git a/drivers/char/radio-sf16fmi.c b/drivers/char/radio-sf16fmi.c index ae975288123d..13659fd85eb6 100644 --- a/drivers/char/radio-sf16fmi.c +++ b/drivers/char/radio-sf16fmi.c @@ -29,6 +29,7 @@ struct fmi_device int port; int curvol; unsigned long curfreq; + int flags; }; #ifndef CONFIG_RADIO_SF16FMI_PORT @@ -39,7 +40,8 @@ static int io = 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) { @@ -69,8 +71,6 @@ static void fmi_unmute(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; @@ -124,9 +124,14 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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))) @@ -140,18 +145,30 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -211,6 +228,7 @@ static struct video_device fmi_radio= fmi_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* Can't poll */ fmi_ioctl, NULL, NULL @@ -225,6 +243,7 @@ __initfunc(int fmi_init(struct video_init *v)) } 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) diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c index b07f4cea1fca..c820c8a36e1a 100644 --- a/drivers/char/radio-zoltrix.c +++ b/drivers/char/radio-zoltrix.c @@ -2,14 +2,14 @@ * (c) 1998 C. van Schaik * * 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 */ @@ -62,31 +62,31 @@ static void zol_mute(struct zol_device *dev) 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; } @@ -95,7 +95,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) { /* 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; @@ -103,10 +103,8 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) 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); @@ -133,29 +131,26 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) 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); @@ -225,7 +220,7 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg) 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; @@ -242,7 +237,7 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if (v.flags & VIDEO_AUDIO_MUTE) zol_mute(rt); else - zol_setvol(rt, v.volume / 6554); + zol_setvol(rt, v.volume / 4096); return 0; } @@ -277,6 +272,7 @@ static struct video_device zoltrix_radio = zol_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, zol_ioctl, NULL, NULL diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index 174c3cc0dd38..868ba4eb958f 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -108,7 +108,6 @@ static ssize_t video_read(struct file *file, } - /* * Write for now does nothing. No reason it shouldnt do overlay setting * for some boards I guess.. @@ -124,6 +123,21 @@ static ssize_t video_write(struct file *file, const char *buf, 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. */ @@ -297,7 +311,7 @@ static struct file_operations video_fops= video_read, video_write, NULL, /* readdir */ - NULL, /* poll */ + video_poll, /* poll */ video_ioctl, video_mmap, video_open, diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index bbeab290c9f9..ca8e80f8e355 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -178,6 +178,9 @@ int el3_probe(struct device *dev) } #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++) @@ -194,6 +197,7 @@ int el3_probe(struct device *dev) mca_adaptor_select_mode(0); } +#endif #endif /* Reset the ISA PnP mechanism on 3c509b. */ @@ -208,7 +212,7 @@ int el3_probe(struct device *dev) 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; diff --git a/drivers/net/plip.c b/drivers/net/plip.c index bcadd467fd5b..6aea631f03c9 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -382,7 +382,7 @@ plip_bh_timeout_error(struct device *dev, struct net_local *nl, 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++; @@ -400,7 +400,7 @@ plip_bh_timeout_error(struct device *dev, struct net_local *nl, 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++; @@ -501,7 +501,7 @@ plip_receive_packet(struct device *dev, struct net_local *nl, 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; @@ -531,13 +531,13 @@ plip_receive_packet(struct device *dev, struct net_local *nl, 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); @@ -565,7 +565,7 @@ plip_receive_packet(struct device *dev, struct net_local *nl, 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; @@ -578,7 +578,7 @@ plip_receive_packet(struct device *dev, struct net_local *nl, 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)); @@ -662,7 +662,7 @@ plip_send_packet(struct device *dev, struct net_local *nl, 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; @@ -699,7 +699,7 @@ plip_send_packet(struct device *dev, struct net_local *nl, } 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; @@ -752,7 +752,7 @@ plip_send_packet(struct device *dev, struct net_local *nl, 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); @@ -791,7 +791,7 @@ plip_error(struct device *dev, struct net_local *nl, 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; @@ -817,7 +817,7 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs) 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; } @@ -830,12 +830,12 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs) 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) { @@ -861,7 +861,7 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs) 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; } } @@ -899,18 +899,18 @@ plip_tx_packet(struct sk_buff *skb, struct device *dev) } 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; @@ -1083,8 +1083,7 @@ plip_get_stats(struct device *dev) 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; @@ -1092,8 +1091,8 @@ plip_config(struct device *dev, struct ifmap *map) 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; diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c index 5340ceddf010..9879f3de0678 100644 --- a/drivers/net/shaper.c +++ b/drivers/net/shaper.c @@ -128,6 +128,7 @@ static int shaper_clocks(struct shaper *shaper, struct sk_buff *skb) static void shaper_setspeed(struct shaper *shaper, int bitspersec) { + shaper->bitspersec=bitspersec; shaper->bytespertick=(bitspersec/HZ)/8; if(!shaper->bytespertick) shaper->bytespertick++; @@ -549,18 +550,28 @@ static int shaper_ioctl(struct device *dev, struct ifreq *ifr, int cmd) { 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; } diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index d8b37d37756a..7d4eaa225b8d 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -48,15 +48,16 @@ typedef u32 (TLanIntVectorFunc)( struct device *, u16 ); 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; diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h index a66e26c2873c..fa1f91bbee14 100644 --- a/drivers/net/tlan.h +++ b/drivers/net/tlan.h @@ -496,6 +496,24 @@ inline void TLan_SetBit(u8 bit, u16 port) #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 ) { @@ -519,7 +537,5 @@ inline u32 TLan_HashFunc( u8 *a ) } - - - +#endif /* I_LIKE_A_FAST_HASH_FUNCTION */ #endif diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 015aef38c379..d15d87a6b88d 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -688,7 +688,7 @@ __initfunc(void tgafb_init(void)) 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; @@ -729,7 +729,7 @@ __initfunc(void tgafb_init(void)) 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; diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index d4fd45d4b8ba..a464d389ace6 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -453,6 +453,8 @@ static int vgacon_switch(struct vc_data *c) */ 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 */ } @@ -933,6 +935,8 @@ static void vgacon_save_screen(struct vc_data *c) 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); } diff --git a/fs/exec.c b/fs/exec.c index 41ca7c2832d6..81de324686e2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -392,7 +392,7 @@ end_readexec: 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); @@ -411,9 +411,16 @@ static int exec_mmap(void) 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); @@ -431,6 +438,8 @@ fail_restore: /* 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: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4c3d876c1ddb..8b398112db52 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1157,10 +1157,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, /* 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; diff --git a/fs/proc/array.c b/fs/proc/array.c index 631665f04d4d..113647683c2c 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -35,6 +35,8 @@ * - Incorporation and non-SMP safe operation * of forissier patch in 2.1.78 by * Hans Marcus + * + * aeb@cwi.nl : /proc/partitions */ #include @@ -1191,6 +1193,7 @@ extern int get_module_list(char *); 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 *); @@ -1250,6 +1253,9 @@ static long get_root_array(char * page, int type, char **start, case PROC_DEVICES: return get_device_list(page); + case PROC_PARTITIONS: + return get_partition_list(page); + case PROC_INTERRUPTS: return get_irq_list(page); diff --git a/fs/proc/generic.c b/fs/proc/generic.c index b161ceb86c5f..a9b00f1f50a3 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -283,7 +283,11 @@ out: 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); } /* diff --git a/fs/proc/root.c b/fs/proc/root.c index 77e7b1585f99..1f5a1ea5d174 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -560,6 +560,11 @@ static struct proc_dir_entry proc_root_devices = { 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, @@ -667,6 +672,7 @@ __initfunc(void proc_root_init(void)) #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); diff --git a/fs/super.c b/fs/super.c index 2842f62787e6..07aa03a63c98 100644 --- a/fs/super.c +++ b/fs/super.c @@ -633,7 +633,7 @@ static void d_mount(struct dentry *covered, struct dentry *dentry) 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; @@ -665,7 +665,7 @@ static int do_umount(kdev_t dev, int unmount_root) * 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); /* @@ -717,7 +717,7 @@ out: 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(); @@ -735,7 +735,7 @@ static int umount_dev(kdev_t dev) down(&mount_sem); - retval = do_umount(dev,0); + retval = do_umount(dev, 0, flags); if (!retval) { fsync_dev(dev); if (dev != ROOT_DEV) { @@ -761,10 +761,11 @@ out: * 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; @@ -794,12 +795,21 @@ asmlinkage int sys_umount(char * name) 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. */ @@ -1263,7 +1273,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old)) 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); diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 8277ab6b240c..9e7184213a16 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -1822,6 +1822,8 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry, put_new_inode = 0; } + clear_inode(old_inode); + rename_done: if (locked) fat_unlock_creation(); diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h index 21ac4e76e1c1..140f5783afc5 100644 --- a/include/asm-alpha/bitops.h +++ b/include/asm-alpha/bitops.h @@ -46,10 +46,10 @@ extern __inline__ void clear_bit(unsigned long nr, volatile void * addr) __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" @@ -66,8 +66,8 @@ extern __inline__ void change_bit(unsigned long nr, volatile void * addr) __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" @@ -109,10 +109,10 @@ extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, __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" @@ -133,9 +133,9 @@ extern __inline__ unsigned long test_and_change_bit(unsigned long nr, __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" @@ -172,6 +172,11 @@ extern inline unsigned long ffz_b(unsigned long x) 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)); @@ -180,6 +185,7 @@ extern inline unsigned long ffz(unsigned long word) bofs = ffz_b(bits); return qofs*8 + bofs; +#endif } #ifdef __KERNEL__ @@ -190,16 +196,34 @@ extern inline unsigned long ffz(unsigned long word) * 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__ */ diff --git a/include/asm-alpha/compiler.h b/include/asm-alpha/compiler.h new file mode 100644 index 000000000000..5656ce953c2c --- /dev/null +++ b/include/asm-alpha/compiler.h @@ -0,0 +1,74 @@ +#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 */ diff --git a/include/asm-alpha/apecs.h b/include/asm-alpha/core_apecs.h similarity index 61% rename from include/asm-alpha/apecs.h rename to include/asm-alpha/core_apecs.h index 3c7b9e09a34b..a8f0bd6efa97 100644 --- a/include/asm-alpha/apecs.h +++ b/include/asm-alpha/core_apecs.h @@ -1,7 +1,9 @@ #ifndef __ALPHA_APECS__H__ #define __ALPHA_APECS__H__ +#include #include +#include /* * APECS is the internal name for the 2107x chipset which provides @@ -18,9 +20,7 @@ * david.rusling@reo.mts.dec.com Initial Version. * */ -#include -#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 @@ -66,7 +66,6 @@ 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) @@ -74,23 +73,20 @@ #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 */ +/* 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) -extern unsigned int APECS_DMA_WIN_BASE; -extern unsigned int APECS_DMA_WIN_SIZE; +#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 -#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. @@ -211,7 +207,7 @@ extern unsigned int APECS_DMA_WIN_SIZE; #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: @@ -226,34 +222,203 @@ extern unsigned int APECS_DMA_WIN_SIZE; #define APECS_IOC_STAT0_P_NBR_SHIFT 13 #define APECS_IOC_STAT0_P_NBR_MASK 0x7ffff -#define HAE_ADDRESS APECS_IOC_HAXR1 +#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 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) + +/* + * 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 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); -#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) +__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 @@ -261,18 +426,13 @@ extern inline void * bus_to_virt(unsigned long address) * 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); + 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 */ + address -= APECS_XL_DMA_WIN2_BASE; + return phys_to_virt(address); } /* @@ -286,17 +446,17 @@ extern inline void * bus_to_virt(unsigned long address) * 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 __inb(unsigned long addr) +__EXTERN_INLINE unsigned int apecs_inb(unsigned long addr) { - long result = *(vuip) ((addr << 5) + APECS_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result = *(vip) ((addr << 5) + APECS_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void apecs_outb(unsigned char b, unsigned long addr) { unsigned int w; @@ -305,14 +465,13 @@ extern inline void __outb(unsigned char b, unsigned long addr) mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int apecs_inw(unsigned long addr) { - long result = *(vuip) ((addr << 5) + APECS_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result = *(vip) ((addr << 5) + APECS_IO + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void apecs_outw(unsigned short b, unsigned long addr) { unsigned int w; @@ -321,12 +480,12 @@ extern inline void __outw(unsigned short b, unsigned long addr) mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int apecs_inl(unsigned long addr) { return *(vuip) ((addr << 5) + APECS_IO + 0x18); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void apecs_outl(unsigned int b, unsigned long addr) { *(vuip) ((addr << 5) + APECS_IO + 0x18) = b; mb(); @@ -337,88 +496,114 @@ extern inline void __outl(unsigned int b, unsigned long addr) * 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) + +__EXTERN_INLINE unsigned long apecs_readb(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, msb; - shift = (addr & 0x3) * 8; if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00); - result >>= shift; - return 0xffUL & result; + result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long apecs_readw(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, msb; - shift = (addr & 0x3) * 8; if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; + result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long apecs_readl(unsigned long addr) { return *(vuip) (addr + APECS_DENSE_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long apecs_readq(unsigned long addr) { return *(vulp) (addr + APECS_DENSE_MEM); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void apecs_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); - } + set_hae(msb); } *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101; } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void apecs_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); - } + set_hae(msb); } *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001; } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr) { *(vuip) (addr + APECS_DENSE_MEM) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__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)) @@ -430,159 +615,13 @@ extern inline void __writeq(unsigned long b, unsigned long addr) #define writel(v,a) __writel((v),(unsigned long)(a)) #define writeq(v,a) __writeq((v),(unsigned long)(a)) -#undef vuip -#undef vulp +#endif /* __WANT_IO_DEF */ -extern unsigned long apecs_init (unsigned long mem_start, - unsigned long mem_end); +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif #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__ */ diff --git a/include/asm-alpha/cia.h b/include/asm-alpha/core_cia.h similarity index 57% rename from include/asm-alpha/cia.h rename to include/asm-alpha/core_cia.h index 93f044b2d883..32fd81f2ed80 100644 --- a/include/asm-alpha/cia.h +++ b/include/asm-alpha/core_cia.h @@ -3,6 +3,7 @@ #include #include +#include /* * CIA is the internal name for the 2117x chipset which provides @@ -21,7 +22,7 @@ /*------------------------------------------------------------------------** ** ** -** EB164 I/O procedures ** +** EB164 I/O procedures ** ** ** ** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** ** inportbxt: 8 bits only ** @@ -72,25 +73,20 @@ * */ -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 +#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 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 */ +#define CIA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define CIA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) -#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 */ +#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) @@ -178,7 +174,6 @@ extern unsigned int CIA_DMA_WIN_SIZE; #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 @@ -194,13 +189,10 @@ extern unsigned int CIA_DMA_WIN_SIZE; #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 +#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: @@ -215,20 +207,100 @@ extern unsigned int CIA_DMA_WIN_SIZE; #define CIA_IOC_STAT0_P_NBR_SHIFT 13 #define CIA_IOC_STAT0_P_NBR_MASK 0x7ffff -#define HAE_ADDRESS CIA_IOC_HAE_MEM +#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 virt_to_bus(void * address) + +__EXTERN_INLINE unsigned long cia_virt_to_bus(void * address) { return virt_to_phys(address) + CIA_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * cia_bus_to_virt(unsigned long address) { return phys_to_virt(address - CIA_DMA_WIN_BASE); } @@ -241,50 +313,47 @@ extern inline void * bus_to_virt(unsigned long address) * 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 __inb(unsigned long addr) +__EXTERN_INLINE unsigned int cia_inb(unsigned long addr) { - long result = *(vuip) ((addr << 5) + CIA_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result; + result = *(vip) ((addr << 5) + CIA_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void cia_outb(unsigned char b, unsigned long addr) { - unsigned int w; - - w = __kernel_insbl(b, addr & 3); + unsigned int w = __kernel_insbl(b, addr & 3); *(vuip) ((addr << 5) + CIA_IO + 0x00) = w; - mb(); + wmb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int cia_inw(unsigned long addr) { - long result = *(vuip) ((addr << 5) + CIA_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result; + result = *(vip) ((addr << 5) + CIA_IO + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void cia_outw(unsigned short b, unsigned long addr) { - unsigned int w; - - w = __kernel_inswl(b, addr & 3); + unsigned int w = __kernel_inswl(b, addr & 3); *(vuip) ((addr << 5) + CIA_IO + 0x08) = w; - mb(); + wmb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int cia_inl(unsigned long addr) { return *(vuip) ((addr << 5) + CIA_IO + 0x18); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr) { *(vuip) ((addr << 5) + CIA_IO + 0x18) = b; - mb(); + wmb(); } @@ -320,287 +389,213 @@ extern inline void __outl(unsigned int b, unsigned long addr) * */ -#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) +__EXTERN_INLINE unsigned long cia_srm_base(unsigned long addr) { - unsigned long result, shift, work; + unsigned long mask, base; - 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); + 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("__readb: address 0x%lx not covered by HAE\n", addr); + printk("cia: address 0x%lx not covered by HAE\n", addr); #endif - return 0x0ffUL; + return 0; } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + + return ((addr & mask) << 5) + base; } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long cia_srm_readb(unsigned long addr) { - unsigned long result, shift, work; + unsigned long result, 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; + 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 void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE unsigned long cia_srm_readw(unsigned long addr) { - unsigned long work; + unsigned long result, 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; + 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 __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void cia_srm_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("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; + unsigned long work = cia_srm_base(addr), w; + if (work) { + work += 0x00; /* add transfer length */ + w = __kernel_insbl(b, addr & 3); + *(vuip) work = w; } - *(vuip) work = b * 0x00010001; } -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long addr) +__EXTERN_INLINE void cia_srm_writew(unsigned short b, 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); + unsigned long work = cia_srm_base(addr), w; + if (work) { + work += 0x08; /* add transfer length */ + w = __kernel_inswl(b, addr & 3); + *(vuip) work = w; } - result = *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) ; - result >>= shift; - return 0xffUL & result; } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long cia_readb(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, 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; + 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 void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE unsigned long cia_readw(unsigned long addr) { - unsigned long msb ; + unsigned long result, msb; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = b * 0x01010101; + 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 __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr) { - unsigned long msb ; + unsigned long msb, w; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = b * 0x00010001; + 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; } -#endif /* SRM_SETUP */ +__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); -extern inline unsigned long __readl(unsigned long addr) + 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 __readq(unsigned long addr) +__EXTERN_INLINE unsigned long cia_readq(unsigned long addr) { return *(vulp) (addr + CIA_DENSE_MEM); } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr) { *(vuip) (addr + CIA_DENSE_MEM) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__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)) -#undef vuip -#undef vulp +#endif /* __WANT_IO_DEF */ -extern unsigned long cia_init (unsigned long mem_start, - unsigned long mem_end); +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif #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__ */ diff --git a/include/asm-alpha/lca.h b/include/asm-alpha/core_lca.h similarity index 73% rename from include/asm-alpha/lca.h rename to include/asm-alpha/core_lca.h index 7eb85b87a061..bce449fa4b95 100644 --- a/include/asm-alpha/lca.h +++ b/include/asm-alpha/core_lca.h @@ -1,6 +1,10 @@ #ifndef __ALPHA_LCA__H__ #define __ALPHA_LCA__H__ +#include +#include +#include + /* * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068, * for example). @@ -52,21 +56,16 @@ * ugh). */ -#include -#include - -#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; +#define LCA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define LCA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) -#else /* SRM_SETUP */ -#define LCA_DMA_WIN_BASE (1024*1024*1024) -#define LCA_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ +#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: @@ -125,7 +124,6 @@ extern unsigned int LCA_DMA_WIN_SIZE; #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: @@ -140,7 +138,7 @@ extern unsigned int LCA_DMA_WIN_SIZE; #define LCA_IOC_STAT0_P_NBR_SHIFT 13 #define LCA_IOC_STAT0_P_NBR_MASK 0x7ffff -#define HAE_ADDRESS LCA_IOC_HAE +#define LCA_HAE_ADDRESS LCA_IOC_HAE /* LCA PMR Power Management register defines */ #define LCA_PMR_ADDR (IDENT_ADDR + 0x120000098UL) @@ -148,43 +146,87 @@ extern unsigned int LCA_DMA_WIN_SIZE; #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_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 LCA_READ_PMR (*(volatile unsigned long *)LCA_PMR_ADDR) +#define LCA_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))) +#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 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 +#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 virt_to_bus(void * address) + +__EXTERN_INLINE unsigned long lca_virt_to_bus(void * address) { return virt_to_phys(address) + LCA_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * lca_bus_to_virt(unsigned long address) { /* * This check is a sanity check but also ensures that bus @@ -208,17 +250,17 @@ extern inline void * bus_to_virt(unsigned long address) * 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 __inb(unsigned long addr) +__EXTERN_INLINE unsigned int lca_inb(unsigned long addr) { - long result = *(vuip) ((addr << 5) + LCA_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result = *(vip) ((addr << 5) + LCA_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void lca_outb(unsigned char b, unsigned long addr) { unsigned int w; @@ -227,14 +269,13 @@ extern inline void __outb(unsigned char b, unsigned long addr) mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int lca_inw(unsigned long addr) { - long result = *(vuip) ((addr << 5) + LCA_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result = *(vip) ((addr << 5) + LCA_IO + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void lca_outw(unsigned short b, unsigned long addr) { unsigned int w; @@ -243,12 +284,12 @@ extern inline void __outw(unsigned short b, unsigned long addr) mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int lca_inl(unsigned long addr) { return *(vuip) ((addr << 5) + LCA_IO + 0x18); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void lca_outl(unsigned int b, unsigned long addr) { *(vuip) ((addr << 5) + LCA_IO + 0x18) = b; mb(); @@ -259,51 +300,44 @@ extern inline void __outl(unsigned int b, unsigned long addr) * 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) + +__EXTERN_INLINE unsigned long lca_readb(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, msb; - shift = (addr & 0x3) * 8; if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - result = *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00); - result >>= shift; - return 0xffUL & result; + result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long lca_readw(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, msb; - shift = (addr & 0x3) * 8; if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - result = *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; + result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long lca_readl(unsigned long addr) { return *(vuip) (addr + LCA_DENSE_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long lca_readq(unsigned long addr) { return *(vulp) (addr + LCA_DENSE_MEM); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void lca_writeb(unsigned char b, unsigned long addr) { unsigned long msb; unsigned int w; @@ -311,15 +345,13 @@ extern inline void __writeb(unsigned char b, unsigned long addr) if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b)); + w = __kernel_insbl(b, addr & 3); *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w; } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void lca_writew(unsigned short b, unsigned long addr) { unsigned long msb; unsigned int w; @@ -327,28 +359,52 @@ extern inline void __writew(unsigned short b, unsigned long addr) if (addr >= (1UL << 24)) { msb = addr & 0xf8000000; addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } + set_hae(msb); } - asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b)); + w = __kernel_inswl(b, addr & 3); *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w; } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr) { *(vuip) (addr + LCA_DENSE_MEM) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void lca_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). - */ +/* 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)) @@ -361,54 +417,13 @@ extern inline void __writeq(unsigned long b, unsigned long addr) #define writel(v,a) __writel((v),(unsigned long)(a)) #define writeq(v,a) __writeq((v),(unsigned long)(a)) -#undef vuip -#undef vulp +#endif /* __WANT_IO_DEF */ -extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end); +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif #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__ */ diff --git a/include/asm-alpha/mcpcia.h b/include/asm-alpha/core_mcpcia.h similarity index 54% rename from include/asm-alpha/mcpcia.h rename to include/asm-alpha/core_mcpcia.h index 116fde5350ed..8b0e03a890d4 100644 --- a/include/asm-alpha/mcpcia.h +++ b/include/asm-alpha/core_mcpcia.h @@ -4,6 +4,7 @@ #include #include #include +#include /* * MCPCIA is the internal name for a core logic chipset which provides @@ -19,7 +20,7 @@ /*------------------------------------------------------------------------** ** ** -** I/O procedures ** +** I/O procedures ** ** ** ** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** ** inportbxt: 8 bits only ** @@ -70,27 +71,23 @@ * */ -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 +#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 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 */ +#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 */ @@ -165,24 +162,38 @@ extern unsigned int MCPCIA_DMA_WIN_SIZE; #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_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) -#define DENSE_MEM(addr) MCPCIA_DENSE(((unsigned long)(addr) >> 32) & 3) +#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; +}; -#define HAE_ADDRESS MCPCIA_HAE_MEM(0) #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 virt_to_bus(void * address) + +__EXTERN_INLINE unsigned long mcpcia_virt_to_bus(void * address) { return virt_to_phys(address) + MCPCIA_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * mcpcia_bus_to_virt(unsigned long address) { return phys_to_virt(address - MCPCIA_DMA_WIN_BASE); } @@ -198,91 +209,56 @@ extern inline void * bus_to_virt(unsigned long address) * 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 * -#ifdef DISABLE_BWIO_ENABLED - -extern inline unsigned int __inb(unsigned long addr) +#if 0 /* BWIO */ +__EXTERN_INLINE unsigned int mcpcia_bw_inb(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO))); - - return result; + return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_IO)); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_outb(unsigned char b, unsigned long addr) { - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO)), "r" (b)); + __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_IO)); + mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int mcpcia_bw_inw(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO))); - - return result; + return __kernel_ldwu(*(vusp)(addr+MCPCIA_BW_IO)); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_outw(unsigned short b, unsigned long addr) { - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO)), "r" (b)); + __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_IO)); + mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int mcpcia_bw_inl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO))); - - return result; + return *(vuip)(addr+MCPCIA_BW_IO); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_outl(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO)), "r" (b)); + *(vuip)(addr+MCPCIA_BW_IO) = b; + mb(); } +#endif -#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) +__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 = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long in_addr) +__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; @@ -293,16 +269,15 @@ extern inline void __outb(unsigned char b, unsigned long in_addr) mb(); } -extern inline unsigned int __inw(unsigned long in_addr) +__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 = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long in_addr) +__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; @@ -313,14 +288,14 @@ extern inline void __outw(unsigned short b, unsigned long in_addr) mb(); } -extern inline unsigned int __inl(unsigned long in_addr) +__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 __outl(unsigned int b, unsigned long in_addr) +__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; @@ -328,14 +303,6 @@ extern inline void __outl(unsigned int b, unsigned long in_addr) 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 @@ -369,322 +336,297 @@ extern inline void __outl(unsigned int b, unsigned long in_addr) * */ -#ifdef DISABLE_BWIO_ENABLED - -extern inline unsigned long __readb(unsigned long addr) +#if 0 /* BWIO */ +__EXTERN_INLINE unsigned long mcpcia_bw_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; + return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_MEM)); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long mcpcia_bw_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; + return __kernel_ldbw(*(vusp)(addr+MCPCIA_BW_MEM)); } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long mcpcia_bw_readl(unsigned long addr) { return *(vuip)(addr + MCPCIA_BW_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long mcpcia_bw_readq(unsigned long addr) { return *(vulp)(addr + MCPCIA_BW_MEM); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_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)); + __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_MEM)); } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_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)); + __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_MEM)); } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_writel(unsigned int b, unsigned long addr) { *(vuip)(addr+MCPCIA_BW_MEM) = b; - mb(); } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void mcpcia_bw_writeq(unsigned long b, unsigned long addr) { *(vulp)(addr+MCPCIA_BW_MEM) = b; - mb(); } +#endif -#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) +__EXTERN_INLINE unsigned long mcpcia_srm_base(unsigned long addr) { - unsigned long result, shift, work; + unsigned long mask, base; + unsigned long hose = (addr >> 32) & 3; - 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); + 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("__readb: address 0x%lx not covered by HAE\n", addr); + printk("mcpcia: address 0x%lx not covered by HAE\n", addr); #endif - return 0x0ffUL; + return 0; } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + + return ((addr & mask) << 5) + base; } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long mcpcia_srm_readb(unsigned long addr) { - unsigned long result, shift, work; + unsigned long result, 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; + 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 void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE unsigned long mcpcia_srm_readw(unsigned long addr) { - unsigned long work; + unsigned long result, 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; + 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 __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void mcpcia_srm_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("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; + unsigned long work = mcpcia_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; } - *(vuip) work = b * 0x00010001; } -#else /* SRM_SETUP */ +__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 __readb(unsigned long in_addr) +__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, shift, msb, work, temp; + unsigned long result, msb, work, temp; - shift = (addr & 0x3) << 3; msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK; - if (msb != hae.cache) { - set_hae(msb); - } + temp = addr & MCPCIA_MEM_R1_MASK; + set_hae(msb); + work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00); - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + result = *(vip) work; + return __kernel_extbl(result, addr & 3); } -extern inline unsigned long __readw(unsigned long in_addr) +__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, shift, msb, work, temp; + unsigned long result, msb, work, temp; - shift = (addr & 0x3) << 3; msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + temp = addr & MCPCIA_MEM_R1_MASK ; + set_hae(msb); + work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08); - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; + result = *(vip) work; + return __kernel_extwl(result, addr & 3); } -extern inline void __writeb(unsigned char b, unsigned long in_addr) +__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 &= MEM_R1_MASK; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= MCPCIA_MEM_R1_MASK; + set_hae(msb); + *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101; } -extern inline void __writew(unsigned short b, unsigned long in_addr) +__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 &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= MCPCIA_MEM_R1_MASK ; + set_hae(msb); + *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001; } -#endif /* SRM_SETUP */ -extern inline unsigned long __readl(unsigned long in_addr) +__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 __readq(unsigned long in_addr) +__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 __writel(unsigned int b, unsigned long in_addr) +__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 __writeq(unsigned long b, unsigned long in_addr) +__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; } -#endif /* BWIO_ENABLED */ +/* Find the DENSE memory area for a given bus address. */ -#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)) +__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 -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; -}; +#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 */ -extern unsigned long mcpcia_init (unsigned long, unsigned long); -extern void mcpcia_fixup (void); +#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 /* __KERNEL__ */ +#endif /* __WANT_IO_DEF */ -/* - * 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 __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 +#endif /* __KERNEL__ */ #endif /* __ALPHA_MCPCIA__H__ */ diff --git a/include/asm-alpha/pyxis.h b/include/asm-alpha/core_pyxis.h similarity index 58% rename from include/asm-alpha/pyxis.h rename to include/asm-alpha/core_pyxis.h index 0369f4858eb3..8b00d1356726 100644 --- a/include/asm-alpha/pyxis.h +++ b/include/asm-alpha/core_pyxis.h @@ -3,6 +3,7 @@ #include #include +#include /* * PYXIS is the internal name for a core logic chipset which provides @@ -18,7 +19,7 @@ /*------------------------------------------------------------------------** ** ** -** I/O procedures ** +** I/O procedures ** ** ** ** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** ** inportbxt: 8 bits only ** @@ -69,25 +70,20 @@ * */ -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 +#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 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 */ +#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) -#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 */ +#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 @@ -165,7 +161,6 @@ extern unsigned int PYXIS_DMA_WIN_SIZE; #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: @@ -201,37 +196,90 @@ extern unsigned int PYXIS_DMA_WIN_SIZE; #define PYXIS_STAT0_P_NBR_SHIFT 13 #define PYXIS_STAT0_P_NBR_MASK 0x7ffff -#define HAE_ADDRESS PYXIS_HAE_MEM +#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. */ -#if defined(CONFIG_ALPHA_RUFFIAN) + /* Ruffian doesn't do 1G PCI window */ -extern inline unsigned long virt_to_bus(void * address) +static inline unsigned long pyxis_ruffian_virt_to_bus(void * address) { return virt_to_phys(address); } -extern inline void * bus_to_virt(unsigned long address) +static inline void * pyxis_ruffian_bus_to_virt(unsigned long address) { return phys_to_virt(address); } -#else /* RUFFIAN */ -extern inline unsigned long virt_to_bus(void * address) + +__EXTERN_INLINE unsigned long pyxis_virt_to_bus(void * address) { return virt_to_phys(address) + PYXIS_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * pyxis_bus_to_virt(unsigned long address) { return phys_to_virt(address - PYXIS_DMA_WIN_BASE); } -#endif /* RUFFIAN */ + /* * I/O functions: @@ -242,82 +290,52 @@ extern inline void * bus_to_virt(unsigned long address) * 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 * -#ifdef BWIO_ENABLED - -extern inline unsigned int __inb(unsigned long addr) +__EXTERN_INLINE unsigned int pyxis_bw_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; + return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_IO)); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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)); + __kernel_stb(b, *(vucp)(addr+PYXIS_BW_IO)); + mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int pyxis_bw_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; + return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_IO)); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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)); + __kernel_stw(b, *(vusp)(addr+PYXIS_BW_IO)); + mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int pyxis_bw_inl(unsigned long addr) { return *(vuip)(addr+PYXIS_BW_IO); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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) +__EXTERN_INLINE unsigned int pyxis_inb(unsigned long addr) { - long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result = *(vip) ((addr << 5) + PYXIS_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void pyxis_outb(unsigned char b, unsigned long addr) { unsigned int w; @@ -326,14 +344,13 @@ extern inline void __outb(unsigned char b, unsigned long addr) mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int pyxis_inw(unsigned long addr) { - long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result = *(vip) ((addr << 5) + PYXIS_IO + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void pyxis_outw(unsigned short b, unsigned long addr) { unsigned int w; @@ -342,25 +359,17 @@ extern inline void __outw(unsigned short b, unsigned long addr) mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int pyxis_inl(unsigned long addr) { return *(vuip) ((addr << 5) + PYXIS_IO + 0x18); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void pyxis_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 @@ -394,331 +403,282 @@ extern inline void __outl(unsigned int b, unsigned long addr) * */ -#ifdef BWIO_ENABLED - -extern inline unsigned long __readb(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_bw_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; + return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_MEM)); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_bw_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; + return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_MEM)); } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_bw_readl(unsigned long addr) { return *(vuip)(addr+PYXIS_BW_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_bw_readq(unsigned long addr) { return *(vulp)(addr+PYXIS_BW_MEM); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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)); + __kernel_stb(b, *(vucp)(addr+PYXIS_BW_MEM)); + mb(); } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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)); + __kernel_stw(b, *(vusp)(addr+PYXIS_BW_MEM)); + mb(); } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_writel(unsigned int b, unsigned long addr) { *(vuip)(addr+PYXIS_BW_MEM) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void pyxis_bw_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) +__EXTERN_INLINE unsigned long pyxis_srm_base(unsigned long addr) { - unsigned long result, shift, work; + unsigned long mask, base; - 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); + 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("__readb: address 0x%lx not covered by HAE\n", addr); + printk("pyxis: address 0x%lx not covered by HAE\n", addr); #endif - return 0x0ffUL; + return 0; } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + + return ((addr & mask) << 5) + base; } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_srm_readb(unsigned long addr) { - unsigned long result, shift, work; + unsigned long result, 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; + 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 void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_srm_readw(unsigned long addr) { - unsigned long work; + unsigned long result, 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; + 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 __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void pyxis_srm_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("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; + unsigned long work = pyxis_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; } - *(vuip) work = b * 0x00010001; } -#else /* SRM_SETUP */ +__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 __readb(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_readb(unsigned long addr) { - unsigned long result, shift, msb, work, temp; + unsigned long result, msb, work, temp; - shift = (addr & 0x3) << 3; msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + temp = addr & PYXIS_MEM_R1_MASK ; + set_hae(msb); + work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00); - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + result = *(vip) work; + return __kernel_extbl(result, addr & 3); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_readw(unsigned long addr) { - unsigned long result, shift, msb, work, temp; + unsigned long result, msb, work, temp; - shift = (addr & 0x3) << 3; msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + temp = addr & PYXIS_MEM_R1_MASK ; + set_hae(msb); + work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08); - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; + result = *(vip) work; + return __kernel_extwl(result, addr & 3); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void pyxis_writeb(unsigned char b, unsigned long addr) { unsigned long msb ; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= PYXIS_MEM_R1_MASK ; + set_hae(msb); + *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101; } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void pyxis_writew(unsigned short b, unsigned long addr) { unsigned long msb ; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= PYXIS_MEM_R1_MASK ; + set_hae(msb); + *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001; } -#endif /* SRM_SETUP */ -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr) { return *(vuip) (addr + PYXIS_DENSE_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr) { return *(vulp) (addr + PYXIS_DENSE_MEM); } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void pyxis_writel(unsigned int b, unsigned long addr) { *(vuip) (addr + PYXIS_DENSE_MEM) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void pyxis_writeq(unsigned long b, unsigned long addr) { *(vulp) (addr + PYXIS_DENSE_MEM) = b; } -#endif /* BWIO_ENABLED */ +/* 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)) -#undef vuip -#undef vulp +#endif /* __WANT_IO_DEF */ -extern unsigned long pyxis_init (unsigned long mem_start, - unsigned long mem_end); +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif #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__ */ diff --git a/include/asm-alpha/t2.h b/include/asm-alpha/core_t2.h similarity index 64% rename from include/asm-alpha/t2.h rename to include/asm-alpha/core_t2.h index ec7100ab89a8..1f0984b383f8 100644 --- a/include/asm-alpha/t2.h +++ b/include/asm-alpha/core_t2.h @@ -3,6 +3,8 @@ #include #include +#include + /* * T2 is the internal name for the core logic chipset which provides @@ -17,29 +19,29 @@ * */ -#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) +#define T2_MEM_R1_MASK 0x03ffffff /* Mem sparse region 1 mask is 26 bits */ -extern unsigned int T2_DMA_WIN_BASE; -extern unsigned int T2_DMA_WIN_SIZE; +#define T2_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define T2_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) -#else /* SRM_SETUP */ -#define T2_DMA_WIN_BASE (1024*1024*1024) -#define T2_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ +#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 */ -#ifdef CONFIG_ALPHA_GAMMA -# define GAMMA_BIAS 0x8000000000UL -#else /* GAMMA */ -# define GAMMA_BIAS 0x0000000000UL -#endif /* GAMMA */ +#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: @@ -48,7 +50,6 @@ extern unsigned int T2_DMA_WIN_SIZE; #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) @@ -71,7 +72,7 @@ extern unsigned int T2_DMA_WIN_SIZE; #define T2_HAE_3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000240UL) #define T2_HAE_4 (IDENT_ADDR + GAMMA_BIAS + 0x38e000260UL) -#define HAE_ADDRESS T2_HAE_1 +#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 @@ -106,27 +107,239 @@ extern unsigned int T2_DMA_WIN_SIZE; * * */ -#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) +#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 virt_to_bus(void * address) + +__EXTERN_INLINE unsigned long t2_virt_to_bus(void * address) { return virt_to_phys(address) + T2_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * t2_bus_to_virt(unsigned long address) { return phys_to_virt(address - T2_DMA_WIN_BASE); } @@ -139,32 +352,31 @@ extern inline void * bus_to_virt(unsigned long address) * get at PCI memory and I/O. */ +#define vip volatile int * #define vuip volatile unsigned int * -extern inline unsigned int __inb(unsigned long addr) +__EXTERN_INLINE unsigned int t2_inb(unsigned long addr) { - long result = *(vuip) ((addr << 5) + T2_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + long result = *(vip) ((addr << 5) + T2_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void t2_outb(unsigned char b, unsigned long addr) { - unsigned int w; + unsigned long w; w = __kernel_insbl(b, addr & 3); *(vuip) ((addr << 5) + T2_IO + 0x00) = w; mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int t2_inw(unsigned long addr) { - long result = *(vuip) ((addr << 5) + T2_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; + long result = *(vip) ((addr << 5) + T2_IO + 0x08); + return __kernel_extwl(result, addr & 3); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void t2_outw(unsigned short b, unsigned long addr) { unsigned int w; @@ -173,12 +385,12 @@ extern inline void __outw(unsigned short b, unsigned long addr) mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int t2_inl(unsigned long addr) { return *(vuip) ((addr << 5) + T2_IO + 0x18); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void t2_outl(unsigned int b, unsigned long addr) { *(vuip) ((addr << 5) + T2_IO + 0x18) = b; mb(); @@ -216,456 +428,264 @@ extern inline void __outl(unsigned int b, unsigned long addr) * 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) +__EXTERN_INLINE unsigned long t2_srm_base(unsigned long addr) { - if ((addr >= t2_sm_base && addr <= t2_sm_base + MEM_R1_MASK) - || (addr >= 512*1024 && addr < 1024*1024)) - return 1; + 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); + printk("T2: address 0x%lx not covered by HAE\n", addr); #endif return 0; } - -extern inline unsigned long __readb(unsigned long addr) +__EXTERN_INLINE unsigned long t2_srm_readb(unsigned long addr) { - unsigned long result, shift, work; + unsigned long result, work; - if (!__t2_addr_check(addr)) - return 0xFF; + if ((work = t2_srm_base(addr)) == 0) + return 0xff; + work += 0x00; /* add transfer length */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - result = *(vuip) work; - shift = (addr & 0x3) << 3; - return (result >> shift) & 0xFF; + result = *(vip) work; + return __kernel_extbl(result, addr & 3); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long t2_srm_readw(unsigned long addr) { - unsigned long result, shift, work; + unsigned long result, work; - if (!__t2_addr_check(addr)) - return 0xFFFF; + if ((work = t2_srm_base(addr)) == 0) + return 0xffff; + work += 0x08; /* add transfer length */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - result = *(vuip) work; - shift = (addr & 0x3) << 3; - return (result >> shift) & 0xFF; + 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 __readl(unsigned long addr) +__EXTERN_INLINE unsigned long t2_srm_readl(unsigned long addr) { unsigned long work; - if (!__t2_addr_check(addr)) - return 0xFFFFFFFF; + if ((work = t2_srm_base(addr)) == 0) + return 0xffffffff; + work += 0x18; /* add transfer length */ - 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) +__EXTERN_INLINE unsigned long t2_srm_readq(unsigned long addr) { unsigned long work, r0, r1; - if (!__t2_addr_check(addr)) + if ((work = t2_srm_base(addr)) == 0) return ~0UL; + work += 0x18; /* add transfer length */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - r0 = *(vuip) work0; - r1 = *(vuip) (work0 + (4 << 5)); + r0 = *(vuip) work; + r1 = *(vuip) (work + (4 << 5)); return r1 << 32 | r0; } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void t2_srm_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; + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; + } } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void t2_srm_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; + 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 __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void t2_srm_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; + 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 __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void t2_srm_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); + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x18; /* add transfer length */ + *(vuip) work = b; + *(vuip) (work + (4 << 5)) = b >> 32; + } } -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long addr) +__EXTERN_INLINE unsigned long t2_readb(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, 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; + 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 __readw(unsigned long addr) +__EXTERN_INLINE unsigned long t2_readw(unsigned long addr) { - unsigned long result, shift, msb; + unsigned long result, msb; - shift = (addr & 0x3) * 8; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; + return __kernel_extwl(result, addr & 3); } -/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */ -extern inline unsigned long __readl(unsigned long addr) +/* 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 result, msb; + unsigned long 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; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long t2_readq(unsigned long addr) { unsigned long r0, r1, work, msb; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + 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 __writeb(unsigned char b, unsigned long addr) + +__EXTERN_INLINE void t2_writeb(unsigned char b, unsigned long addr) { unsigned long msb ; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101; } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void t2_writew(unsigned short b, unsigned long addr) { unsigned long msb ; msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + 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 __writel(unsigned int b, unsigned long addr) +/* 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 &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void t2_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); - } + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + work = (addr << 5) + T2_SPARSE_MEM + 0x18; *(vuip)work = b; *(vuip)(work + (4 << 5)) = b >> 32; } -#endif /* SRM_SETUP */ +/* Find the DENSE memory area for a given bus address. */ -#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))) +__EXTERN_INLINE unsigned long t2_dense_mem(unsigned long addr) +{ + return T2_DENSE_MEM; +} +#undef vip #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. */ -}; - +#ifdef __WANT_IO_DEF -/* - * 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 */ -}; +#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 -/* - * 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 */ -}; +#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 -/* - * 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; -}; +#define dense_mem t2_dense_mem -/* - * 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 */ -}; +#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))) -/* - * 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 */ -}; +#endif /* __WANT_IO_DEF */ +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 +#endif /* __KERNEL__ */ #endif /* __ALPHA_T2__H__ */ diff --git a/include/asm-alpha/tsunami.h b/include/asm-alpha/core_tsunami.h similarity index 81% rename from include/asm-alpha/tsunami.h rename to include/asm-alpha/core_tsunami.h index fe48e2861290..5da9c08bbefd 100644 --- a/include/asm-alpha/tsunami.h +++ b/include/asm-alpha/core_tsunami.h @@ -3,6 +3,7 @@ #include #include +#include /* * TSUNAMI/TYPHOON are the internal names for the core logic chipset which @@ -15,22 +16,18 @@ * */ -#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 */ +#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 @@ -287,20 +284,30 @@ union TPchipPERRMASK { #define TSUNAMI_PCI1_IO (IDENT_ADDR + TS_BIAS + 0x3FC000000UL) #define TSUNAMI_PCI1_CONF (IDENT_ADDR + TS_BIAS + 0x3FE000000UL) -#define HAE_ADDRESS 0 +/* + * 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 virt_to_bus(void * address) +__EXTERN_INLINE unsigned long tsunami_virt_to_bus(void * address) { return virt_to_phys(address) + TSUNAMI_DMA_WIN_BASE; } -extern inline void * bus_to_virt(unsigned long address) +__EXTERN_INLINE void * tsunami_bus_to_virt(unsigned long address) { return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE); } @@ -315,49 +322,46 @@ extern inline void * bus_to_virt(unsigned long address) /* HACK ALERT! HACK ALERT! */ /* HACK ALERT! HACK ALERT! */ -/* only using PCI bus 0 for now in all routines */ +/* Only using PCI bus 0 for now in all routines. */ -#define DENSE_MEM(addr) TSUNAMI_PCI0_MEM +#define TSUNAMI_IACK_SC TSUNAMI_PCI0_IACK_SC /* 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) +__EXTERN_INLINE unsigned int tsunami_inb(unsigned long addr) { - return *(vucp)(addr + TSUNAMI_PCI0_IO); + return __kernel_ldbu(*(vucp)(addr + TSUNAMI_PCI0_IO)); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void tsunami_outb(unsigned char b, unsigned long addr) { - *(vucp)(addr + TSUNAMI_PCI0_IO) = b; + __kernel_stb(b, *(vucp)(addr + TSUNAMI_PCI0_IO)); mb(); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int tsunami_inw(unsigned long addr) { - return *(vusp)(addr+TSUNAMI_PCI0_IO); + return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_IO)); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void tsunami_outw(unsigned short b, unsigned long addr) { - *(vusp)(addr+TSUNAMI_PCI0_IO) = b; + __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_IO)); mb(); } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int tsunami_inl(unsigned long addr) { return *(vuip)(addr+TSUNAMI_PCI0_IO); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void tsunami_outl(unsigned int b, unsigned long addr) { *(vuip)(addr+TSUNAMI_PCI0_IO) = b; mb(); @@ -367,50 +371,83 @@ extern inline void __outl(unsigned int b, unsigned long addr) * Memory functions. all accesses are done through linear space. */ -extern inline unsigned long __readb(unsigned long addr) +__EXTERN_INLINE unsigned long tsunami_readb(unsigned long addr) { - return *(vucp)(addr+TSUNAMI_PCI0_MEM); + return __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_MEM)); } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long tsunami_readw(unsigned long addr) { - return *(vusp)(addr+TSUNAMI_PCI0_MEM); + return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_MEM)); } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long tsunami_readl(unsigned long addr) { return *(vuip)(addr+TSUNAMI_PCI0_MEM); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long tsunami_readq(unsigned long addr) { return *(vulp)(addr+TSUNAMI_PCI0_MEM); } -extern inline void __writeb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void tsunami_writeb(unsigned char b, unsigned long addr) { - *(vucp)(addr+TSUNAMI_PCI0_MEM) = b; + __kernel_stb(b, *(vucp)(addr+TSUNAMI_PCI0_MEM)); mb(); } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void tsunami_writew(unsigned short b, unsigned long addr) { - *(vusp)(addr+TSUNAMI_PCI0_MEM) = b; + __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_MEM)); mb(); } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void tsunami_writel(unsigned int b, unsigned long addr) { *(vuip)(addr+TSUNAMI_PCI0_MEM) = b; mb(); } -extern inline void __writeq(unsigned long b, unsigned long addr) +__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)) @@ -429,23 +466,13 @@ extern inline void __writeq(unsigned long b, unsigned long addr) #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 +#endif /* __WANT_IO_DEF */ -extern unsigned long tsunami_init (unsigned long, unsigned long); +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif #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__ */ diff --git a/include/asm-alpha/dma.h b/include/asm-alpha/dma.h index 738a15b7677f..69fc00f85b80 100644 --- a/include/asm-alpha/dma.h +++ b/include/asm-alpha/dma.h @@ -19,8 +19,7 @@ #define _ASM_DMA_H #include - -#include /* need byte IO */ +#include #define dma_outb outb #define dma_inb inb @@ -75,7 +74,6 @@ #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 for more info. @@ -86,12 +84,18 @@ We MUST coordinate the maximum with 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 */ diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h index 9be100c4fb4c..d72e85c39dba 100644 --- a/include/asm-alpha/floppy.h +++ b/include/asm-alpha/floppy.h @@ -51,13 +51,24 @@ static int FDC2 = -1; #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 */ diff --git a/include/asm-alpha/hwrpb.h b/include/asm-alpha/hwrpb.h index 6909f0b6bdb4..5aaf9422390b 100644 --- a/include/asm-alpha/hwrpb.h +++ b/include/asm-alpha/hwrpb.h @@ -1,5 +1,5 @@ -#ifndef _HWRPB_H -#define _HWRPB_H +#ifndef __ALPHA_HWRPB_H +#define __ALPHA_HWRPB_H #define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000) @@ -34,6 +34,7 @@ #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 */ @@ -92,7 +93,7 @@ struct percpu_struct { 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; }; @@ -184,4 +185,6 @@ struct hwrpb_struct { unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */ }; -#endif +extern struct hwrpb_struct *hwrpb; + +#endif /* __ALPHA_HWRPB_H */ diff --git a/include/asm-alpha/init.h b/include/asm-alpha/init.h index 9ce618965c70..7d769dfcd0fc 100644 --- a/include/asm-alpha/init.h +++ b/include/asm-alpha/init.h @@ -7,12 +7,6 @@ __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 diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h index e65a7308f0cf..61da10c8e076 100644 --- a/include/asm-alpha/io.h +++ b/include/asm-alpha/io.h @@ -2,29 +2,17 @@ #define __ALPHA_IO_H #include - #include +#include /* 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 @@ -40,25 +28,34 @@ extern struct hae { * 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); } @@ -76,45 +73,79 @@ extern void _sethae (unsigned long addr); /* cached version */ #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 /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_APECS) -# include /* 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 #elif defined(CONFIG_ALPHA_CIA) -# include /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_T2) -# include /* get chip-specific definitions */ +# include +#elif defined(CONFIG_ALPHA_LCA) +# include +#elif defined(CONFIG_ALPHA_MCPCIA) +# include #elif defined(CONFIG_ALPHA_PYXIS) -# include /* get chip-specific definitions */ +# include +#elif defined(CONFIG_ALPHA_T2) +# include #elif defined(CONFIG_ALPHA_TSUNAMI) -# include /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_MCPCIA) -# include /* get chip-specific definitions */ -#else +# include +#elif defined(CONFIG_ALPHA_JENSEN) # include +#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 @@ -190,12 +221,12 @@ extern void _writeq(unsigned long b, unsigned long addr); * 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) { } @@ -263,8 +294,9 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); #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 { @@ -279,6 +311,29 @@ out: 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 */ diff --git a/include/asm-alpha/irq.h b/include/asm-alpha/irq.h index 7140a1437020..7f8853c5584c 100644 --- a/include/asm-alpha/irq.h +++ b/include/asm-alpha/irq.h @@ -10,18 +10,24 @@ #include #include -#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) || \ @@ -29,29 +35,52 @@ 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) { /* @@ -64,4 +93,4 @@ static __inline__ int irq_cannonicalize(int irq) extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); -#endif +#endif /* _ALPHA_IRQ_H */ diff --git a/include/asm-alpha/jensen.h b/include/asm-alpha/jensen.h index ff0ad54b5886..75f99ea33261 100644 --- a/include/asm-alpha/jensen.h +++ b/include/asm-alpha/jensen.h @@ -1,6 +1,8 @@ #ifndef __ALPHA_JENSEN_H #define __ALPHA_JENSEN_H +#include + /* * Defines for the AlphaPC EISA IO and memory address space. */ @@ -66,6 +68,14 @@ */ #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. * @@ -73,10 +83,16 @@ * 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 @@ -86,16 +102,19 @@ * * 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 @@ -108,36 +127,31 @@ extern inline void __set_hae(unsigned long addr) * 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(); } @@ -146,131 +160,165 @@ extern inline void __bus_outb(unsigned char b, unsigned long addr) * 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). @@ -281,17 +329,13 @@ extern inline void __writeq(unsigned long b, unsigned long addr) #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 */ diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h new file mode 100644 index 000000000000..e3d247a9a9d3 --- /dev/null +++ b/include/asm-alpha/machvec.h @@ -0,0 +1,118 @@ +#ifndef __ALPHA_MACHVEC_H +#define __ALPHA_MACHVEC_H 1 + +#include +#include + + +/* 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 */ diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index 0d4ab6b214c7..af97b6740906 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -9,6 +9,7 @@ #include #include +#include /* * The maximum ASN's the processor supports. On the EV4 this is 63 @@ -32,11 +33,17 @@ * 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__ @@ -78,26 +85,21 @@ extern unsigned long asn_cache; * 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) { @@ -106,27 +108,81 @@ extern inline void get_mmu_context(struct task_struct *p) 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 */ diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h new file mode 100644 index 000000000000..2dd28c3ccc23 --- /dev/null +++ b/include/asm-alpha/pci.h @@ -0,0 +1,48 @@ +#ifndef __ALPHA_PCI_H +#define __ALPHA_PCI_H + +#include +#include + + +/* + * 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 */ diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index e9a8fb47bd13..3cbbaa17aa26 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -13,6 +13,8 @@ #include #include /* For TASK_SIZE */ #include +#include + /* Caches aren't brain-dead on the Alpha. */ #define flush_cache_all() do { } while (0) @@ -22,62 +24,88 @@ #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. */ diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h index b98290660f32..3cbf6d573fbc 100644 --- a/include/asm-alpha/posix_types.h +++ b/include/asm-alpha/posix_types.h @@ -34,6 +34,8 @@ typedef struct { int val[2]; } __kernel_fsid_t; +#ifdef __KERNEL__ + #ifndef __GNUC__ #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) @@ -109,4 +111,6 @@ static __inline__ void __FD_ZERO(__kernel_fd_set *p) #endif /* __GNUC__ */ +#endif /* __KERNEL__ */ + #endif /* _ALPHA_POSIX_TYPES_H */ diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h index dbeee15fbfb8..803ba998a317 100644 --- a/include/asm-alpha/processor.h +++ b/include/asm-alpha/processor.h @@ -82,13 +82,23 @@ struct thread_struct { * 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; } /* diff --git a/include/asm-alpha/string.h b/include/asm-alpha/string.h index e21e56eb1de7..11495a0b689f 100644 --- a/include/asm-alpha/string.h +++ b/include/asm-alpha/string.h @@ -56,6 +56,8 @@ extern void * __memsetw(void *dest, unsigned short, size_t count); ? __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__ */ diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h index 72b91317ef43..a4f18c347ab2 100644 --- a/include/asm-alpha/system.h +++ b/include/asm-alpha/system.h @@ -100,7 +100,7 @@ extern void wripir(unsigned long); #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); @@ -108,6 +108,9 @@ 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") diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 017ee2ba5ff3..f56ce91e7071 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h @@ -113,37 +113,6 @@ extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) : "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..) */ diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index aa5aa860575c..1b23625c626a 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h @@ -27,7 +27,7 @@ #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 @@ -57,7 +57,7 @@ #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 diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 29f2149eca80..b2b747d20fbb 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -26,6 +26,7 @@ #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 diff --git a/include/linux/if_shaper.h b/include/linux/if_shaper.h index 7377867e70ee..57ffd730ae2a 100644 --- a/include/linux/if_shaper.h +++ b/include/linux/if_shaper.h @@ -18,6 +18,7 @@ struct shaper { struct sk_buff_head sendq; __u32 bytespertick; + __u32 bitspersec; __u32 shapelatency; __u32 shapeclock; __u32 recovery; /* Time we can next clock a packet out on @@ -44,6 +45,8 @@ struct shaper #define SHAPER_SET_DEV 0x0001 #define SHAPER_SET_SPEED 0x0002 +#define SHAPER_GET_DEV 0x0003 +#define SHAPER_GET_SPEED 0x0004 struct shaperconf { diff --git a/include/linux/if_wic.h b/include/linux/if_wic.h deleted file mode 100644 index cca15f85bcc6..000000000000 --- a/include/linux/if_wic.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _LINUX_IF_WIC_H -#define _LINUX_IF_WIC_H - -#include - -#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 */ - - diff --git a/include/linux/mount.h b/include/linux/mount.h index a0dbd0eaaa86..7e7ccb266cb6 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -37,4 +37,10 @@ struct vfsmount struct vfsmount *lookup_vfsmnt(kdev_t dev); +/* + * Umount options + */ + +#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ + #endif /* _LINUX_MOUNT_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index f8437c686b18..aefb1bf40ddd 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -31,6 +31,7 @@ enum root_directory_inos { PROC_MODULES, PROC_STAT, PROC_DEVICES, + PROC_PARTITIONS, PROC_INTERRUPTS, PROC_FILESYSTEMS, PROC_KSYMS, diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 7d3ffc97372f..701fb8870659 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + struct video_device { char name[32]; @@ -14,6 +16,7 @@ struct video_device 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 *); @@ -109,6 +112,10 @@ struct video_picture #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 @@ -160,7 +167,7 @@ struct video_mmap { 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 @@ -205,6 +212,7 @@ 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 diff --git a/ipc/msg.c b/ipc/msg.c index e505bcc01684..217967e026f9 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -29,7 +29,7 @@ static int used_queues = 0; static int max_msqid = 0; static struct wait_queue *msg_lock = NULL; -__initfunc(void msg_init (void)) +void __init msg_init (void) { int id; @@ -47,16 +47,11 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg 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; @@ -103,8 +98,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg 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 { @@ -117,7 +110,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg msq->msg_qnum++; msq->msg_lspid = current->pid; msq->msg_stime = CURRENT_TIME; - restore_flags(flags); wake_up (&msq->rwait); return 0; } @@ -129,16 +121,9 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty 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]; @@ -160,8 +145,6 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty return -EACCES; } - save_flags(flags); - cli(); if (msgtyp == 0) nmsg = msq->msg_first; else if (msgtyp > 0) { @@ -186,15 +169,12 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty 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 { @@ -214,10 +194,10 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty 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 */ @@ -395,19 +375,16 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) 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; @@ -427,23 +404,21 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) 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; } @@ -471,8 +446,9 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) 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; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index b815fd0378d1..e9cb2ea7046f 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -51,6 +51,7 @@ #include #include #include +#include extern unsigned char aux_device_present, pckbd_read_mask; @@ -389,7 +390,7 @@ EXPORT_SYMBOL(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); @@ -397,3 +398,6 @@ EXPORT_SYMBOL(put_write_access); /* dynamic registering of consoles */ EXPORT_SYMBOL(register_console); EXPORT_SYMBOL(unregister_console); + +/* time */ +EXPORT_SYMBOL(get_fast_time); diff --git a/mm/swap.c b/mm/swap.c index 6be5b48c2fd1..3cedb215c8b7 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -67,9 +67,9 @@ swap_control_t swap_control = { 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 = { diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 3edee0168d65..71999a41652c 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1009,7 +1009,10 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 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) diff --git a/net/core/dev.c b/net/core/dev.c index cfb9298c4d25..a17baa52f640 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -740,21 +740,20 @@ static inline void handle_bridge(struct sk_buff *skb, unsigned short type) * 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 diff --git a/net/econet/econet.c b/net/econet/econet.c index 5b5a543357f0..92bdc4c97f01 100644 --- a/net/econet/econet.c +++ b/net/econet/econet.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ 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 @@ -343,7 +346,7 @@ static int econet_sendmsg(struct socket *sock, struct msghdr *msg, int len, eb->cookie = saddr->cookie; eb->sec = *saddr; - eb->sent - ec_tx_done; + eb->sent = ec_tx_done; if (dev->hard_header) { int res; @@ -965,7 +968,6 @@ static void aun_data_available(struct sock *sk, int slen) * drop the packet. */ -static spinlock_t aun_queue_lock; static void ab_cleanup(unsigned long h) { diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 39ed076ed511..e6e272b0e605 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -163,7 +163,7 @@ static struct neigh_ops arp_direct_ops = 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 = { @@ -261,7 +261,7 @@ static int arp_constructor(struct neighbour *neigh) 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: diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5f760d394fb6..1e5a509d473c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1204,8 +1204,8 @@ struct proto_ops packet_ops = { packet_release, packet_bind, sock_no_connect, - NULL, - NULL, + sock_no_socketpair, + sock_no_accept, packet_getname, datagram_poll, packet_ioctl, -- 2.39.5